From 9b78061c8fb83202973d509b9af24f0a12786958 Mon Sep 17 00:00:00 2001 From: Dudejoe870 Date: Tue, 28 May 2024 22:25:16 -0500 Subject: Initial hash directive implementation --- src/check_expr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 8672941c1..2e008fe93 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7414,7 +7414,8 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c name == "config" || name == "load" || name == "load_directory" || - name == "load_hash" + name == "load_hash" || + name == "hash" ) { operand->mode = Addressing_Builtin; operand->builtin_id = BuiltinProc_DIRECTIVE; -- cgit v1.2.3 From 6b386631ddd7305f3111310a2ed3f921d5035298 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 4 Jun 2024 16:16:27 +0100 Subject: Improve error message suggestion for passing enums to integers --- src/check_expr.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2e008fe93..6af80eed5 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -125,6 +125,8 @@ gb_internal Entity *find_polymorphic_record_entity(GenTypesData *found_gen_types gb_internal bool complete_soa_type(Checker *checker, Type *t, bool wait_to_finish); +gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y); + enum LoadDirectiveResult { LoadDirective_Success = 0, LoadDirective_Error = 1, @@ -2252,6 +2254,17 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i gb_internal bool check_integer_exceed_suggestion(CheckerContext *c, Operand *o, Type *type, i64 max_bit_size=0) { if (is_type_integer(type) && o->value.kind == ExactValue_Integer) { gbString b = type_to_string(type); + defer (gb_string_free(b)); + + if (is_type_enum(o->type)) { + if (check_is_castable_to(c, o, type)) { + gbString ot = type_to_string(o->type); + error_line("\tSuggestion: Try casting the '%s' expression to '%s'", ot, b); + gb_string_free(ot); + } + return true; + } + i64 sz = type_size_of(type); i64 bit_size = 8*sz; @@ -2301,7 +2314,6 @@ gb_internal bool check_integer_exceed_suggestion(CheckerContext *c, Operand *o, } } - gb_string_free(b); return true; } -- cgit v1.2.3 From b47a15733df5d0cb858a2be0d4eb334df3d50536 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 4 Jun 2024 19:06:13 +0200 Subject: implement `#exists(path)` --- src/check_builtin.cpp | 94 ++++++++++++++++++++++++++++++++++++++------------- src/check_expr.cpp | 1 + src/checker.hpp | 9 +++++ 3 files changed, 80 insertions(+), 24 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 15c63905e..7e3bcb7ee 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1079,7 +1079,7 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return false; } -gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String const &original_string, bool err_on_not_found, LoadFileCache **cache_) { +gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String const &original_string, bool err_on_not_found, LoadFileCache **cache_, LoadFileTier tier) { ast_node(ce, CallExpr, call); ast_node(bd, BasicDirective, ce->proc); String builtin_name = bd->name.string; @@ -1105,12 +1105,16 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String gbFileError file_error = gbFileError_None; String data = {}; + bool exists = false; + LoadFileTier cache_tier = LoadFileTier_Invalid; LoadFileCache **cache_ptr = string_map_get(&c->info->load_file_cache, path); LoadFileCache *cache = cache_ptr ? *cache_ptr : nullptr; if (cache) { file_error = cache->file_error; data = cache->data; + exists = cache->exists; + cache_tier = cache->tier; } defer ({ if (cache == nullptr) { @@ -1118,60 +1122,78 @@ gb_internal bool cache_load_file_directive(CheckerContext *c, Ast *call, String new_cache->path = path; new_cache->data = data; new_cache->file_error = file_error; + new_cache->exists = exists; + new_cache->tier = cache_tier; string_map_init(&new_cache->hashes, 32); string_map_set(&c->info->load_file_cache, path, new_cache); if (cache_) *cache_ = new_cache; } else { cache->data = data; cache->file_error = file_error; + cache->exists = exists; + cache->tier = cache_tier; if (cache_) *cache_ = cache; } }); - TEMPORARY_ALLOCATOR_GUARD(); - char *c_str = alloc_cstring(temporary_allocator(), path); + if (tier > cache_tier) { + cache_tier = tier; - gbFile f = {}; - if (cache == nullptr) { + TEMPORARY_ALLOCATOR_GUARD(); + char *c_str = alloc_cstring(temporary_allocator(), path); + + gbFile f = {}; file_error = gb_file_open(&f, c_str); + defer (gb_file_close(&f)); + + if (file_error == gbFileError_None) { + exists = true; + + switch(tier) { + case LoadFileTier_Exists: + // Nothing to do. + break; + case LoadFileTier_Contents: { + isize file_size = cast(isize)gb_file_size(&f); + if (file_size > 0) { + u8 *ptr = cast(u8 *)gb_alloc(permanent_allocator(), file_size+1); + gb_file_read_at(&f, ptr, file_size, 0); + ptr[file_size] = '\0'; + data.text = ptr; + data.len = file_size; + } + break; + } + default: + GB_PANIC("Unhandled LoadFileTier"); + }; + } } - defer (gb_file_close(&f)); switch (file_error) { default: case gbFileError_Invalid: if (err_on_not_found) { - error(ce->proc, "Failed to `#%.*s` file: %s; invalid file or cannot be found", LIT(builtin_name), c_str); + error(ce->proc, "Failed to `#%.*s` file: %.*s; invalid file or cannot be found", LIT(builtin_name), LIT(path)); } call->state_flags |= StateFlag_DirectiveWasFalse; return false; case gbFileError_NotExists: if (err_on_not_found) { - error(ce->proc, "Failed to `#%.*s` file: %s; file cannot be found", LIT(builtin_name), c_str); + error(ce->proc, "Failed to `#%.*s` file: %.*s; file cannot be found", LIT(builtin_name), LIT(path)); } call->state_flags |= StateFlag_DirectiveWasFalse; return false; case gbFileError_Permission: if (err_on_not_found) { - error(ce->proc, "Failed to `#%.*s` file: %s; file permissions problem", LIT(builtin_name), c_str); + error(ce->proc, "Failed to `#%.*s` file: %.*s; file permissions problem", LIT(builtin_name), LIT(path)); } call->state_flags |= StateFlag_DirectiveWasFalse; return false; case gbFileError_None: // Okay break; - } - - if (cache == nullptr) { - isize file_size = cast(isize)gb_file_size(&f); - if (file_size > 0) { - u8 *ptr = cast(u8 *)gb_alloc(permanent_allocator(), file_size+1); - gb_file_read_at(&f, ptr, file_size, 0); - ptr[file_size] = '\0'; - data.text = ptr; - data.len = file_size; - } - } + }; return true; } @@ -1263,7 +1285,7 @@ gb_internal LoadDirectiveResult check_load_directive(CheckerContext *c, Operand operand->mode = Addressing_Constant; LoadFileCache *cache = nullptr; - if (cache_load_file_directive(c, call, o.value.value_string, err_on_not_found, &cache)) { + if (cache_load_file_directive(c, call, o.value.value_string, err_on_not_found, &cache, LoadFileTier_Contents)) { operand->value = exact_value_string(cache->data); return LoadDirective_Success; } @@ -1391,7 +1413,7 @@ gb_internal LoadDirectiveResult check_load_directory_directive(CheckerContext *c for (FileInfo fi : list) { LoadFileCache *cache = nullptr; - if (cache_load_file_directive(c, call, fi.fullpath, err_on_not_found, &cache)) { + if (cache_load_file_directive(c, call, fi.fullpath, err_on_not_found, &cache, LoadFileTier_Contents)) { array_add(&file_caches, cache); } else { result = LoadDirective_Error; @@ -1490,6 +1512,30 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o operand->type = t_source_code_location; operand->mode = Addressing_Value; + } else if (name == "exists") { + if (ce->args.count != 1) { + error(ce->close, "'#exists' expects 1 argument, got %td", ce->args.count); + return false; + } + + Operand o = {}; + check_expr(c, &o, ce->args[0]); + if (o.mode != Addressing_Constant || !is_type_string(o.type)) { + error(ce->args[0], "'#exists' expected a constant string argument"); + return false; + } + + operand->type = t_untyped_bool; + operand->mode = Addressing_Constant; + + String original_string = o.value.value_string; + LoadFileCache *cache = nullptr; + if (cache_load_file_directive(c, call, original_string, /* err_on_not_found=*/ false, &cache, LoadFileTier_Exists)) { + operand->value = exact_value_bool(cache->exists); + } else { + operand->value = exact_value_bool(false); + } + } else if (name == "load") { return check_load_directive(c, operand, call, type_hint, true) == LoadDirective_Success; } else if (name == "load_directory") { @@ -1542,7 +1588,7 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o String hash_kind = o_hash.value.value_string; LoadFileCache *cache = nullptr; - if (cache_load_file_directive(c, call, original_string, true, &cache)) { + if (cache_load_file_directive(c, call, original_string, true, &cache, LoadFileTier_Contents)) { MUTEX_GUARD(&c->info->load_file_mutex); // TODO(bill): make these procedures fast :P u64 hash_value = 0; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2e008fe93..3bf2af24a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7408,6 +7408,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c String name = bd->name.string; if ( name == "location" || + name == "exists" || name == "assert" || name == "panic" || name == "defined" || diff --git a/src/checker.hpp b/src/checker.hpp index 539b72b2d..e793540e3 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -336,7 +336,16 @@ struct ObjcMsgData { ObjcMsgKind kind; Type *proc_type; }; + +enum LoadFileTier { + LoadFileTier_Invalid, + LoadFileTier_Exists, + LoadFileTier_Contents, +}; + struct LoadFileCache { + LoadFileTier tier; + bool exists; String path; gbFileError file_error; String data; -- cgit v1.2.3 From 3e159736cdf7654d5739a1340458aa23aaccbf7a Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 4 Jun 2024 19:32:23 +0200 Subject: use `#exists` to provide good errors for common missing libraries --- src/check_expr.cpp | 1 + vendor/cgltf/cgltf.odin | 22 ++++++++++++++++++---- vendor/miniaudio/common.odin | 12 ++++++++---- vendor/miniaudio/data_conversion.odin | 6 +----- vendor/miniaudio/decoding.odin | 6 +----- vendor/miniaudio/device_io_procs.odin | 6 +----- vendor/miniaudio/effects.odin | 6 +----- vendor/miniaudio/encoding.odin | 6 +----- vendor/miniaudio/engine.odin | 6 +----- vendor/miniaudio/filtering.odin | 6 +----- vendor/miniaudio/generation.odin | 6 +----- vendor/miniaudio/job_queue.odin | 6 +----- vendor/miniaudio/logging.odin | 6 +----- vendor/miniaudio/node_graph.odin | 6 +----- vendor/miniaudio/resource_manager.odin | 6 +----- vendor/miniaudio/synchronization.odin | 6 +----- vendor/miniaudio/utilities.odin | 6 +----- vendor/miniaudio/vfs.odin | 6 +----- vendor/stb/image/stb_image.odin | 25 +++++++++++++++++++------ vendor/stb/image/stb_image_resize.odin | 23 ++++++++++++++++++----- vendor/stb/image/stb_image_write.odin | 21 +++++++++++++++++---- vendor/stb/rect_pack/stb_rect_pack.odin | 21 +++++++++++++++++---- vendor/stb/truetype/stb_truetype.odin | 22 +++++++++++++++++----- vendor/stb/vorbis/stb_vorbis.odin | 24 +++++++++++++++++------- 24 files changed, 147 insertions(+), 114 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 3bf2af24a..c03fcb184 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8330,6 +8330,7 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A name == "assert" || name == "defined" || name == "config" || + name == "exists" || name == "load" || name == "load_hash" || name == "load_directory" || diff --git a/vendor/cgltf/cgltf.odin b/vendor/cgltf/cgltf.odin index 024e8dfaa..a5d474a7b 100644 --- a/vendor/cgltf/cgltf.odin +++ b/vendor/cgltf/cgltf.odin @@ -1,9 +1,23 @@ package cgltf -when ODIN_OS == .Windows { foreign import lib "lib/cgltf.lib" } -else when ODIN_OS == .Linux { foreign import lib "lib/cgltf.a" } -else when ODIN_OS == .Darwin { foreign import lib "lib/darwin/cgltf.a" } -else { foreign import lib "system:cgltf" } +@(private) +LIB :: ( + "lib/cgltf.lib" when ODIN_OS == .Windows + else "lib/cgltf.a" when ODIN_OS == .Linux + else "lib/darwin/cgltf.a" when ODIN_OS == .Darwin + else "" +) + +when LIB != "" { + when !#exists(LIB) { + // Windows library is shipped with the compiler, so a Windows specific message should not be needed. + #panic("Could not find the compiled cgltf library, it can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/cgltf/src\"`") + } + + foreign import lib { LIB } +} else { + foreign import lib "system:cgltf" +} import "core:c" diff --git a/vendor/miniaudio/common.odin b/vendor/miniaudio/common.odin index b38599d96..d72c3f251 100644 --- a/vendor/miniaudio/common.odin +++ b/vendor/miniaudio/common.odin @@ -8,12 +8,16 @@ when MINIAUDIO_SHARED { #panic("Shared linking for miniaudio is not supported yet") } -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" +@(private) +LIB :: "lib/miniaudio.lib" when ODIN_OS == .Windows else "lib/miniaudio.a" + +when !#exists(LIB) { + // Windows library is shipped with the compiler, so a Windows specific message should not be needed. + #panic("Could not find the compiled miniaudio library, it can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/miniaudio/src\"`") } +foreign import lib { LIB } + BINDINGS_VERSION_MAJOR :: 0 BINDINGS_VERSION_MINOR :: 11 BINDINGS_VERSION_REVISION :: 21 diff --git a/vendor/miniaudio/data_conversion.odin b/vendor/miniaudio/data_conversion.odin index aee26bc8c..c33f54707 100644 --- a/vendor/miniaudio/data_conversion.odin +++ b/vendor/miniaudio/data_conversion.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /************************************************************************************************************************************************************ ************************************************************************************************************************************************************* diff --git a/vendor/miniaudio/decoding.odin b/vendor/miniaudio/decoding.odin index 4433aa5a7..4860680c9 100644 --- a/vendor/miniaudio/decoding.odin +++ b/vendor/miniaudio/decoding.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /************************************************************************************************************************************************************ diff --git a/vendor/miniaudio/device_io_procs.odin b/vendor/miniaudio/device_io_procs.odin index 0d572ae2c..21ac1afd7 100644 --- a/vendor/miniaudio/device_io_procs.odin +++ b/vendor/miniaudio/device_io_procs.odin @@ -1,10 +1,6 @@ package miniaudio -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } import "core:c" diff --git a/vendor/miniaudio/effects.odin b/vendor/miniaudio/effects.odin index 273845001..a3710ad88 100644 --- a/vendor/miniaudio/effects.odin +++ b/vendor/miniaudio/effects.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /* Delay diff --git a/vendor/miniaudio/encoding.odin b/vendor/miniaudio/encoding.odin index 63aa45c6d..da8389b06 100644 --- a/vendor/miniaudio/encoding.odin +++ b/vendor/miniaudio/encoding.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /************************************************************************************************************************************************************ diff --git a/vendor/miniaudio/engine.odin b/vendor/miniaudio/engine.odin index 6eabd75c2..ecd3fb39d 100644 --- a/vendor/miniaudio/engine.odin +++ b/vendor/miniaudio/engine.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /************************************************************************************************************************************************************ diff --git a/vendor/miniaudio/filtering.odin b/vendor/miniaudio/filtering.odin index 31ddbd7a4..d1c053d20 100644 --- a/vendor/miniaudio/filtering.odin +++ b/vendor/miniaudio/filtering.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /************************************************************************************************************************************************************** diff --git a/vendor/miniaudio/generation.odin b/vendor/miniaudio/generation.odin index 69be85234..746efcca7 100644 --- a/vendor/miniaudio/generation.odin +++ b/vendor/miniaudio/generation.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } waveform_type :: enum c.int { sine, diff --git a/vendor/miniaudio/job_queue.odin b/vendor/miniaudio/job_queue.odin index baa71c5f1..01ee31216 100644 --- a/vendor/miniaudio/job_queue.odin +++ b/vendor/miniaudio/job_queue.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /* Slot Allocator diff --git a/vendor/miniaudio/logging.odin b/vendor/miniaudio/logging.odin index 52b1c7980..afddf8e68 100644 --- a/vendor/miniaudio/logging.odin +++ b/vendor/miniaudio/logging.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c/libc" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } MAX_LOG_CALLBACKS :: 4 diff --git a/vendor/miniaudio/node_graph.odin b/vendor/miniaudio/node_graph.odin index 09ab50a3b..63482413b 100644 --- a/vendor/miniaudio/node_graph.odin +++ b/vendor/miniaudio/node_graph.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /************************************************************************************************************************************************************ diff --git a/vendor/miniaudio/resource_manager.odin b/vendor/miniaudio/resource_manager.odin index f27f3a53a..0284db86b 100644 --- a/vendor/miniaudio/resource_manager.odin +++ b/vendor/miniaudio/resource_manager.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /************************************************************************************************************************************************************ diff --git a/vendor/miniaudio/synchronization.odin b/vendor/miniaudio/synchronization.odin index cd4b0a5f0..012f52c2c 100644 --- a/vendor/miniaudio/synchronization.odin +++ b/vendor/miniaudio/synchronization.odin @@ -1,10 +1,6 @@ package miniaudio -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } @(default_calling_convention="c", link_prefix="ma_") foreign lib { diff --git a/vendor/miniaudio/utilities.odin b/vendor/miniaudio/utilities.odin index d518a514a..8728f40dc 100644 --- a/vendor/miniaudio/utilities.odin +++ b/vendor/miniaudio/utilities.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } @(default_calling_convention="c", link_prefix="ma_") foreign lib { diff --git a/vendor/miniaudio/vfs.odin b/vendor/miniaudio/vfs.odin index 475d118fc..b045a1501 100644 --- a/vendor/miniaudio/vfs.odin +++ b/vendor/miniaudio/vfs.odin @@ -2,11 +2,7 @@ package miniaudio import "core:c" -when ODIN_OS == .Windows { - foreign import lib "lib/miniaudio.lib" -} else { - foreign import lib "lib/miniaudio.a" -} +foreign import lib { LIB } /************************************************************************************************************************************************************ diff --git a/vendor/stb/image/stb_image.odin b/vendor/stb/image/stb_image.odin index c7caf801e..828a1c2bd 100644 --- a/vendor/stb/image/stb_image.odin +++ b/vendor/stb/image/stb_image.odin @@ -2,13 +2,26 @@ package stb_image import c "core:c/libc" -#assert(size_of(c.int) == size_of(b32)) - - when ODIN_OS == .Windows { foreign import stbi "../lib/stb_image.lib" } -else when ODIN_OS == .Linux { foreign import stbi "../lib/stb_image.a" } -else when ODIN_OS == .Darwin { foreign import stbi "../lib/darwin/stb_image.a" } -else { foreign import stbi "system:stb_image" } +@(private) +LIB :: ( + "../lib/stb_image.lib" when ODIN_OS == .Windows + else "../lib/stb_image.a" when ODIN_OS == .Linux + else "../lib/darwin/stb_image.a" when ODIN_OS == .Darwin + else "" +) + +when LIB != "" { + when !#exists(LIB) { + // The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed. + #panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`") + } + + foreign import stbi { LIB } +} else { + foreign import stbi "system:stb_image" +} +#assert(size_of(c.int) == size_of(b32)) #assert(size_of(b32) == size_of(c.int)) // diff --git a/vendor/stb/image/stb_image_resize.odin b/vendor/stb/image/stb_image_resize.odin index c464964df..d407a1852 100644 --- a/vendor/stb/image/stb_image_resize.odin +++ b/vendor/stb/image/stb_image_resize.odin @@ -2,11 +2,24 @@ package stb_image import c "core:c/libc" - when ODIN_OS == .Windows { foreign import lib "../lib/stb_image_resize.lib" } -else when ODIN_OS == .Linux { foreign import lib "../lib/stb_image_resize.a" } -else when ODIN_OS == .Darwin { foreign import lib "../lib/darwin/stb_image_resize.a" } -else { foreign import lib "system:stb_image_resize" } - +@(private) +RESIZE_LIB :: ( + "../lib/stb_image_resize.lib" when ODIN_OS == .Windows + else "../lib/stb_image_resize.a" when ODIN_OS == .Linux + else "../lib/darwin/stb_image_resize.a" when ODIN_OS == .Darwin + else "" +) + +when RESIZE_LIB != "" { + when !#exists(RESIZE_LIB) { + // The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed. + #panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`") + } + + foreign import lib { RESIZE_LIB } +} else { + foreign import lib "system:stb_image_resize" +} ////////////////////////////////////////////////////////////////////////////// // diff --git a/vendor/stb/image/stb_image_write.odin b/vendor/stb/image/stb_image_write.odin index 9ed97eb48..f030f1e28 100644 --- a/vendor/stb/image/stb_image_write.odin +++ b/vendor/stb/image/stb_image_write.odin @@ -2,11 +2,24 @@ package stb_image import c "core:c/libc" - when ODIN_OS == .Windows { foreign import stbiw "../lib/stb_image_write.lib" } -else when ODIN_OS == .Linux { foreign import stbiw "../lib/stb_image_write.a" } -else when ODIN_OS == .Darwin { foreign import stbiw "../lib/darwin/stb_image_write.a" } -else { foreign import stbiw "system:stb_image_write" } +@(private) +WRITE_LIB :: ( + "../lib/stb_image_write.lib" when ODIN_OS == .Windows + else "../lib/stb_image_write.a" when ODIN_OS == .Linux + else "../lib/darwin/stb_image_write.a" when ODIN_OS == .Darwin + else "" +) +when WRITE_LIB != "" { + when !#exists(WRITE_LIB) { + // The STB libraries are shipped with the compiler on Windows so a Windows specific message should not be needed. + #panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`") + } + + foreign import stbiw { WRITE_LIB } +} else { + foreign import stbiw "system:stb_image_write" +} write_func :: proc "c" (ctx: rawptr, data: rawptr, size: c.int) diff --git a/vendor/stb/rect_pack/stb_rect_pack.odin b/vendor/stb/rect_pack/stb_rect_pack.odin index 3a2544b81..6c0b56378 100644 --- a/vendor/stb/rect_pack/stb_rect_pack.odin +++ b/vendor/stb/rect_pack/stb_rect_pack.odin @@ -4,10 +4,23 @@ import "core:c" #assert(size_of(b32) == size_of(c.int)) - when ODIN_OS == .Windows { foreign import lib "../lib/stb_rect_pack.lib" } -else when ODIN_OS == .Linux { foreign import lib "../lib/stb_rect_pack.a" } -else when ODIN_OS == .Darwin { foreign import lib "../lib/darwin/stb_rect_pack.a" } -else { foreign import lib "system:stb_rect_pack" } +@(private) +LIB :: ( + "../lib/stb_rect_pack.lib" when ODIN_OS == .Windows + else "../lib/stb_rect_pack.a" when ODIN_OS == .Linux + else "../lib/darwin/stb_rect_pack.a" when ODIN_OS == .Darwin + else "" +) + +when LIB != "" { + when !#exists(LIB) { + #panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`") + } + + foreign import lib { LIB } +} else { + foreign import lib "system:stb_rect_pack" +} Coord :: distinct c.int _MAXVAL :: max(Coord) diff --git a/vendor/stb/truetype/stb_truetype.odin b/vendor/stb/truetype/stb_truetype.odin index 1600041de..876138c3a 100644 --- a/vendor/stb/truetype/stb_truetype.odin +++ b/vendor/stb/truetype/stb_truetype.odin @@ -3,11 +3,23 @@ package stb_truetype import c "core:c" import stbrp "vendor:stb/rect_pack" - when ODIN_OS == .Windows { foreign import stbtt "../lib/stb_truetype.lib" } -else when ODIN_OS == .Linux { foreign import stbtt "../lib/stb_truetype.a" } -else when ODIN_OS == .Darwin { foreign import stbtt "../lib/darwin/stb_truetype.a" } -else { foreign import stbtt "system:stb_truetype" } - +@(private) +LIB :: ( + "../lib/stb_truetype.lib" when ODIN_OS == .Windows + else "../lib/stb_truetype.a" when ODIN_OS == .Linux + else "../lib/darwin/stb_truetype.a" when ODIN_OS == .Darwin + else "" +) + +when LIB != "" { + when !#exists(LIB) { + #panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`") + } + + foreign import stbtt { LIB } +} else { + foreign import stbtt "system:stb_truetype" +} /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/vendor/stb/vorbis/stb_vorbis.odin b/vendor/stb/vorbis/stb_vorbis.odin index 0c887a473..867ffb86d 100644 --- a/vendor/stb/vorbis/stb_vorbis.odin +++ b/vendor/stb/vorbis/stb_vorbis.odin @@ -2,13 +2,23 @@ package stb_vorbis import c "core:c/libc" - - when ODIN_OS == .Windows { foreign import lib "../lib/stb_vorbis.lib" } -else when ODIN_OS == .Linux { foreign import lib "../lib/stb_vorbis.a" } -else when ODIN_OS == .Darwin { foreign import lib "../lib/darwin/stb_vorbis.a" } -else { foreign import lib "system:stb_vorbis" } - - +@(private) +LIB :: ( + "../lib/stb_vorbis.lib" when ODIN_OS == .Windows + else "../lib/stb_vorbis.a" when ODIN_OS == .Linux + else "../lib/darwin/stb_vorbis.a" when ODIN_OS == .Darwin + else "" +) + +when LIB != "" { + when !#exists(LIB) { + #panic("Could not find the compiled STB libraries, they can be compiled by running `make -C \"" + ODIN_ROOT + "vendor/stb/src\"`") + } + + foreign import lib { LIB } +} else { + foreign import lib "system:stb_vorbis" +} /////////// THREAD SAFETY -- cgit v1.2.3 From cbabcb0907e6430571c14d21fcb09c150275d99b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 5 Jun 2024 15:43:15 +0100 Subject: Fix #3682 --- src/check_expr.cpp | 7 +++++++ src/llvm_backend_expr.cpp | 20 ++++++++++++++++++-- src/types.cpp | 9 +++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 0830f65bd..d2d01deda 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8866,6 +8866,10 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, SliceArray.elem; break; + case Type_BitField: + is_constant = false; + ft = bt->BitField.fields[index]->type; + break; default: GB_PANIC("invalid type: %s", type_to_string(ft)); break; @@ -8892,6 +8896,9 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, SliceArray.elem; break; + case Type_BitField: + nested_ft = bt->BitField.fields[index]->type; + break; default: GB_PANIC("invalid type %s", type_to_string(nested_ft)); break; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index c12489598..7772ba930 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4533,10 +4533,26 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { if (lb_is_nested_possibly_constant(type, sel, elem)) { continue; } - lbValue dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sel); field_expr = lb_build_expr(p, elem); field_expr = lb_emit_conv(p, field_expr, sel.entity->type); - lb_emit_store(p, dst, field_expr); + if (sel.is_bit_field) { + Selection sub_sel = trim_selection(sel); + lbValue trimmed_dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sub_sel); + Type *bf = base_type(type_deref(trimmed_dst.type)); + if (is_type_pointer(bf)) { + trimmed_dst = lb_emit_load(p, trimmed_dst); + bf = base_type(type_deref(trimmed_dst.type)); + } + GB_ASSERT(bf->kind == Type_BitField); + + isize idx = sel.index[sel.index.count-1]; + lbAddr dst = lb_addr_bit_field(trimmed_dst, bf->BitField.fields[idx]->type, bf->BitField.bit_offsets[idx], bf->BitField.bit_sizes[idx]); + lb_addr_store(p, dst, field_expr); + + } else { + lbValue dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sel); + lb_emit_store(p, dst, field_expr); + } continue; } diff --git a/src/types.cpp b/src/types.cpp index e568d2af2..618e5bd8a 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -457,6 +457,15 @@ gb_internal Selection sub_selection(Selection const &sel, isize offset) { return res; } +gb_internal Selection trim_selection(Selection const &sel) { + Selection res = {}; + res.index.data = sel.index.data; + res.index.count = gb_max(sel.index.count - 1, 0); + res.index.capacity = res.index.count; + return res; +} + + gb_global Type basic_types[] = { {Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}}, -- cgit v1.2.3 From 7044a7d77650e922a66f3bfe99711f3ed370e1ba Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 6 Jun 2024 23:55:48 +0100 Subject: Try to fix a possible race condition with polymorphic record parameters --- src/check_builtin.cpp | 31 ++++++++----------------------- src/check_expr.cpp | 11 +++-------- src/check_type.cpp | 30 +++++++++++++----------------- src/checker.cpp | 4 ++++ src/types.cpp | 18 ++++++++++++++++++ 5 files changed, 46 insertions(+), 48 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 7e3bcb7ee..eef925d94 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -5912,15 +5912,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (operand->mode != Addressing_Type) { error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name)); } else { - Type *bt = base_type(operand->type); - if (bt->kind == Type_Struct) { - if (bt->Struct.polymorphic_params != nullptr) { - operand->value = exact_value_i64(bt->Struct.polymorphic_params->Tuple.variables.count); - } - } else if (bt->kind == Type_Union) { - if (bt->Union.polymorphic_params != nullptr) { - operand->value = exact_value_i64(bt->Union.polymorphic_params->Tuple.variables.count); - } + TypeTuple *tuple = get_record_polymorphic_params(operand->type); + if (tuple) { + operand->value = exact_value_i64(tuple->variables.count); } else { error(operand->expr, "Expected a record type for '%.*s'", LIT(builtin_name)); } @@ -5952,20 +5946,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As Entity *param = nullptr; i64 count = 0; - Type *bt = base_type(operand->type); - if (bt->kind == Type_Struct) { - if (bt->Struct.polymorphic_params != nullptr) { - count = bt->Struct.polymorphic_params->Tuple.variables.count; - if (index < count) { - param = bt->Struct.polymorphic_params->Tuple.variables[cast(isize)index]; - } - } - } else if (bt->kind == Type_Union) { - if (bt->Union.polymorphic_params != nullptr) { - count = bt->Union.polymorphic_params->Tuple.variables.count; - if (index < count) { - param = bt->Union.polymorphic_params->Tuple.variables[cast(isize)index]; - } + TypeTuple *tuple = get_record_polymorphic_params(operand->type); + if (tuple) { + count = tuple->variables.count; + if (index < count) { + param = tuple->variables[cast(isize)index]; } } else { error(operand->expr, "Expected a specialized polymorphic record type for '%.*s'", LIT(builtin_name)); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index d2d01deda..ad546858c 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7331,14 +7331,9 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O gbString s = gb_string_make_reserve(heap_allocator(), e->token.string.len+3); s = gb_string_append_fmt(s, "%.*s(", LIT(e->token.string)); - Type *params = nullptr; - switch (bt->kind) { - case Type_Struct: params = bt->Struct.polymorphic_params; break; - case Type_Union: params = bt->Union.polymorphic_params; break; - } - - if (params != nullptr) for_array(i, params->Tuple.variables) { - Entity *v = params->Tuple.variables[i]; + TypeTuple *tuple = get_record_polymorphic_params(e->type); + if (tuple != nullptr) for_array(i, tuple->variables) { + Entity *v = tuple->variables[i]; String name = v->token.string; if (i > 0) { s = gb_string_append_fmt(s, ", "); diff --git a/src/check_type.cpp b/src/check_type.cpp index 7ed657bee..e0dea19cb 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -564,19 +564,7 @@ gb_internal bool check_record_poly_operand_specialization(CheckerContext *ctx, T gb_internal Entity *find_polymorphic_record_entity(GenTypesData *found_gen_types, isize param_count, Array const &ordered_operands) { for (Entity *e : found_gen_types->types) { Type *t = base_type(e->type); - TypeTuple *tuple = nullptr; - switch (t->kind) { - case Type_Struct: - if (t->Struct.polymorphic_params) { - tuple = &t->Struct.polymorphic_params->Tuple; - } - break; - case Type_Union: - if (t->Union.polymorphic_params) { - tuple = &t->Union.polymorphic_params->Tuple; - } - break; - } + TypeTuple *tuple = get_record_polymorphic_params(t); GB_ASSERT_MSG(tuple != nullptr, "%s :: %s", type_to_string(e->type), type_to_string(t)); GB_ASSERT(param_count == tuple->variables.count); @@ -663,6 +651,8 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast * &struct_type->Struct.is_polymorphic, node, poly_operands ); + wait_signal_set(&struct_type->Struct.polymorphic_wait_signal); + struct_type->Struct.is_poly_specialized = check_record_poly_operand_specialization(ctx, struct_type, poly_operands, &struct_type->Struct.is_polymorphic); if (original_type_for_poly) { GB_ASSERT(named_type != nullptr); @@ -712,6 +702,8 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no &union_type->Union.is_polymorphic, node, poly_operands ); + wait_signal_set(&union_type->Union.polymorphic_wait_signal); + union_type->Union.is_poly_specialized = check_record_poly_operand_specialization(ctx, union_type, poly_operands, &union_type->Union.is_polymorphic); if (original_type_for_poly) { GB_ASSERT(named_type != nullptr); @@ -1453,12 +1445,14 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special return true; } + wait_for_record_polymorphic_params(s); + wait_for_record_polymorphic_params(t); if (t->Struct.polymorphic_parent == s->Struct.polymorphic_parent && s->Struct.polymorphic_params != nullptr && t->Struct.polymorphic_params != nullptr) { - TypeTuple *s_tuple = &s->Struct.polymorphic_params->Tuple; - TypeTuple *t_tuple = &t->Struct.polymorphic_params->Tuple; + TypeTuple *s_tuple = get_record_polymorphic_params(s); + TypeTuple *t_tuple = get_record_polymorphic_params(t); GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count); for_array(i, s_tuple->variables) { Entity *s_e = s_tuple->variables[i]; @@ -1506,12 +1500,14 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special return true; } + wait_for_record_polymorphic_params(s); + wait_for_record_polymorphic_params(t); if (t->Union.polymorphic_parent == s->Union.polymorphic_parent && s->Union.polymorphic_params != nullptr && t->Union.polymorphic_params != nullptr) { - TypeTuple *s_tuple = &s->Union.polymorphic_params->Tuple; - TypeTuple *t_tuple = &t->Union.polymorphic_params->Tuple; + TypeTuple *s_tuple = get_record_polymorphic_params(s); + TypeTuple *t_tuple = get_record_polymorphic_params(t); GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count); for_array(i, s_tuple->variables) { Entity *s_e = s_tuple->variables[i]; diff --git a/src/checker.cpp b/src/checker.cpp index 8a58bb425..e90509c1f 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2031,6 +2031,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { } else { add_type_info_type_internal(c, t_type_info_ptr); } + wait_for_record_polymorphic_params(bt); add_type_info_type_internal(c, bt->Union.polymorphic_params); for_array(i, bt->Union.variants) { add_type_info_type_internal(c, bt->Union.variants[i]); @@ -2063,6 +2064,7 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { } } } + wait_for_record_polymorphic_params(bt); add_type_info_type_internal(c, bt->Struct.polymorphic_params); for_array(i, bt->Struct.fields) { Entity *f = bt->Struct.fields[i]; @@ -2292,6 +2294,7 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { } else { add_min_dep_type_info(c, t_type_info_ptr); } + wait_for_record_polymorphic_params(bt); add_min_dep_type_info(c, bt->Union.polymorphic_params); for_array(i, bt->Union.variants) { add_min_dep_type_info(c, bt->Union.variants[i]); @@ -2321,6 +2324,7 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { } } } + wait_for_record_polymorphic_params(bt); add_min_dep_type_info(c, bt->Struct.polymorphic_params); for_array(i, bt->Struct.fields) { Entity *f = bt->Struct.fields[i]; diff --git a/src/types.cpp b/src/types.cpp index 45aa26894..4ceba5244 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -140,6 +140,7 @@ struct TypeStruct { i64 custom_field_align; Type * polymorphic_params; // Type_Tuple Type * polymorphic_parent; + Wait_Signal polymorphic_wait_signal; Type * soa_elem; i32 soa_count; @@ -167,6 +168,7 @@ struct TypeUnion { i64 custom_align; Type * polymorphic_params; // Type_Tuple Type * polymorphic_parent; + Wait_Signal polymorphic_wait_signal; i16 tag_size; bool is_polymorphic; @@ -1093,6 +1095,7 @@ gb_internal Type *alloc_type_struct() { gb_internal Type *alloc_type_struct_complete() { Type *t = alloc_type(Type_Struct); wait_signal_set(&t->Struct.fields_wait_signal); + wait_signal_set(&t->Struct.polymorphic_wait_signal); return t; } @@ -2136,15 +2139,30 @@ gb_internal bool is_type_polymorphic_record_unspecialized(Type *t) { return false; } +gb_internal void wait_for_record_polymorphic_params(Type *t) { + t = base_type(t); + switch (t->kind) { + case Type_Struct: + wait_signal_until_available(&t->Struct.polymorphic_wait_signal); + break; + case Type_Union: + wait_signal_until_available(&t->Union.polymorphic_wait_signal); + break; + } +} + + gb_internal TypeTuple *get_record_polymorphic_params(Type *t) { t = base_type(t); switch (t->kind) { case Type_Struct: + wait_signal_until_available(&t->Struct.polymorphic_wait_signal); if (t->Struct.polymorphic_params) { return &t->Struct.polymorphic_params->Tuple; } break; case Type_Union: + wait_signal_until_available(&t->Union.polymorphic_wait_signal); if (t->Union.polymorphic_params) { return &t->Union.polymorphic_params->Tuple; } -- cgit v1.2.3 From 4b52f7fe2bd68d74efffa55ef8b4582164c1e268 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 9 Jun 2024 13:35:22 +0100 Subject: Fix #3713 --- src/check_expr.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index ad546858c..4115cd1e9 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3336,11 +3336,12 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { } if (is_type_untyped(x->type)) { - Type *final_type = type; - if (is_const_expr && !is_type_constant_type(type)) { - final_type = default_type(x->type); - } - update_untyped_expr_type(c, x->expr, final_type, true); + convert_to_typed(c, x, type); + // Type *final_type = type; + // if (is_const_expr && !is_type_constant_type(type)) { + // final_type = default_type(x->type); + // } + // update_untyped_expr_type(c, x->expr, final_type, true); } else { Type *src = core_type(x->type); Type *dst = core_type(type); @@ -4286,7 +4287,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar } else { switch (operand->type->Basic.kind) { case Basic_UntypedBool: - if (!is_type_boolean(target_type)) { + if (!is_type_boolean(target_type) && + !is_type_integer(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); return; @@ -7527,9 +7529,6 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } operand->type = t; operand->expr = call; - if (operand->mode != Addressing_Invalid) { - update_untyped_expr_type(c, arg, t, false); - } break; } } -- cgit v1.2.3 From c17981ac38ace6cac12463029273d16068bf23c3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 9 Jun 2024 14:02:01 +0100 Subject: Add edge case to `error_operand_no_value` --- src/check_expr.cpp | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 4115cd1e9..1e6d6e2ab 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -281,8 +281,20 @@ gb_internal void error_operand_not_expression(Operand *o) { gb_internal void error_operand_no_value(Operand *o) { if (o->mode == Addressing_NoValue) { - gbString err = expr_to_string(o->expr); Ast *x = unparen_expr(o->expr); + + if (x->kind == Ast_CallExpr) { + Ast *p = unparen_expr(x->CallExpr.proc); + if (p->kind == Ast_BasicDirective) { + String tag = p->BasicDirective.name.string; + if (tag == "panic" || + tag == "assert") { + return; + } + } + } + + gbString err = expr_to_string(o->expr); if (x->kind == Ast_CallExpr) { error(o->expr, "'%s' call does not return a value and cannot be used as a value", err); } else { @@ -3336,12 +3348,11 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { } if (is_type_untyped(x->type)) { - convert_to_typed(c, x, type); - // Type *final_type = type; - // if (is_const_expr && !is_type_constant_type(type)) { - // final_type = default_type(x->type); - // } - // update_untyped_expr_type(c, x->expr, final_type, true); + Type *final_type = type; + if (is_const_expr && !is_type_constant_type(type)) { + final_type = default_type(x->type); + } + update_untyped_expr_type(c, x->expr, final_type, true); } else { Type *src = core_type(x->type); Type *dst = core_type(type); @@ -4287,8 +4298,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar } else { switch (operand->type->Basic.kind) { case Basic_UntypedBool: - if (!is_type_boolean(target_type) && - !is_type_integer(target_type)) { + if (!is_type_boolean(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); return; @@ -7529,6 +7539,9 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c } operand->type = t; operand->expr = call; + if (operand->mode != Addressing_Invalid) { + update_untyped_expr_type(c, arg, t, false); + } break; } } @@ -8336,7 +8349,7 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A name == "assert" || name == "defined" || name == "config" || - name == "exists" || + name == "exists" || name == "load" || name == "load_hash" || name == "load_directory" || -- cgit v1.2.3 From ef7c6b98951aacc72bd25750e1c4a3a8c30c7d06 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 9 Jun 2024 14:07:07 +0100 Subject: Re Fix #3713 --- src/check_expr.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 1e6d6e2ab..13d0e277d 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3350,6 +3350,9 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { if (is_type_untyped(x->type)) { Type *final_type = type; if (is_const_expr && !is_type_constant_type(type)) { + if (is_type_union(type)) { + convert_to_typed(c, x, type); + } final_type = default_type(x->type); } update_untyped_expr_type(c, x->expr, final_type, true); @@ -4298,7 +4301,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar } else { switch (operand->type->Basic.kind) { case Basic_UntypedBool: - if (!is_type_boolean(target_type)) { + if (!is_type_boolean(target_type) && + !is_type_integer(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); return; -- cgit v1.2.3 From 45d1328a85818fc77f2aacc77fa6ce0cfbce3473 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:50:16 -0400 Subject: Fix typo in a `#force_inline` error message --- src/check_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 13d0e277d..641f70566 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7672,7 +7672,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c if (decl->proc_lit) { ast_node(pl, ProcLit, decl->proc_lit); if (pl->inlining == ProcInlining_no_inline) { - error(call, "'#force_inline' cannot be applied to a procedure that has be marked as '#force_no_inline'"); + error(call, "'#force_inline' cannot be applied to a procedure that has been marked as '#force_no_inline'"); } } } -- cgit v1.2.3 From fa3cae2bb04db76f52f1b2288a9c858f20332b8a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 10 Jun 2024 15:02:34 +0100 Subject: Add `intrinsics.procedure_of` ```odin foo :: proc(x: $T) { fmt.println(x) } bar :: intrinsics.procedure_of(foo(int(123))) // parameters are never ran at compile time, similar to `size_of` bar(333) // prints 333 ``` --- base/intrinsics/intrinsics.odin | 4 ++++ src/check_builtin.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ src/check_decl.cpp | 17 ++++++++++----- src/check_expr.cpp | 1 + src/check_stmt.cpp | 10 ++++++++- src/checker.cpp | 4 ++++ src/checker.hpp | 6 ++++++ src/checker_builtin_procs.hpp | 4 ++++ src/parser.hpp | 1 + 9 files changed, 87 insertions(+), 6 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index 8873f3bbc..4f6fa2713 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -295,6 +295,10 @@ simd_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T --- // if all listed features are supported. has_target_feature :: proc($test: $T) -> bool where type_is_string(T) || type_is_proc(T) --- + +// Returns the value of the procedure where `x` must be a call expression +procedure_of :: proc(x: $T) -> T where type_is_proc(T) --- + // WASM targets only wasm_memory_grow :: proc(index, delta: uintptr) -> int --- wasm_memory_size :: proc(index: uintptr) -> int --- diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 98c695a2c..3aee804df 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1843,6 +1843,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_objc_register_class: case BuiltinProc_atomic_type_is_lock_free: case BuiltinProc_has_target_feature: + case BuiltinProc_procedure_of: // NOTE(bill): The first arg may be a Type, this will be checked case by case break; @@ -6157,6 +6158,51 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } + case BuiltinProc_procedure_of: + { + Ast *call_expr = unparen_expr(ce->args[0]); + Operand op = {}; + check_expr_base(c, &op, ce->args[0], nullptr); + if (op.mode != Addressing_Value && !(call_expr && call_expr->kind == Ast_CallExpr)) { + error(ce->args[0], "Expected a call expression for '%.*s'", LIT(builtin_name)); + return false; + } + + Ast *proc = call_expr->CallExpr.proc; + Entity *e = entity_of_node(proc); + + if (e == nullptr) { + error(ce->args[0], "Invalid procedure value, expected a regular/specialized procedure"); + return false; + } + + TypeAndValue tav = proc->tav; + + + operand->type = e->type; + operand->mode = Addressing_Value; + operand->value = tav.value; + operand->builtin_id = BuiltinProc_Invalid; + operand->proc_group = nullptr; + + if (tav.mode == Addressing_Builtin) { + operand->mode = tav.mode; + operand->builtin_id = cast(BuiltinProcId)e->Builtin.id; + break; + } + + if (!is_type_proc(e->type)) { + gbString s = type_to_string(e->type); + error(ce->args[0], "Expected a procedure value, got '%s'", s); + gb_string_free(s); + return false; + } + + + ce->entity_procedure_of = e; + break; + } + case BuiltinProc_constant_utf16_cstring: { String value = {}; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 43947836b..13b14149a 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -88,11 +88,14 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o e->type = t_invalid; return nullptr; } else if (is_type_polymorphic(t)) { - gbString str = type_to_string(t); - defer (gb_string_free(str)); - error(e->token, "Invalid use of a polymorphic type '%s' in %.*s", str, LIT(context_name)); - e->type = t_invalid; - return nullptr; + Entity *e = entity_of_node(operand->expr); + if (e->state.load() != EntityState_Resolved) { + gbString str = type_to_string(t); + defer (gb_string_free(str)); + error(e->token, "Invalid use of a polymorphic type '%s' in %.*s", str, LIT(context_name)); + e->type = t_invalid; + return nullptr; + } } else if (is_type_empty_union(t)) { gbString str = type_to_string(t); defer (gb_string_free(str)); @@ -479,6 +482,9 @@ gb_internal void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr entity = check_selector(ctx, &operand, init, e->type); } else { check_expr_or_type(ctx, &operand, init, e->type); + if (init->kind == Ast_CallExpr) { + entity = init->CallExpr.entity_procedure_of; + } } switch (operand.mode) { @@ -526,6 +532,7 @@ gb_internal void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr return; } + if (entity != nullptr) { if (e->type != nullptr) { Operand x = {}; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 641f70566..01cba881e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -578,6 +578,7 @@ gb_internal bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, E d->defer_use_checked = false; Entity *entity = alloc_entity_procedure(nullptr, token, final_proc_type, tags); + entity->state.store(EntityState_Resolved); entity->identifier = ident; add_entity_and_decl_info(&nctx, ident, entity, d); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index c37c58cd6..f2e3b0242 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2224,8 +2224,16 @@ gb_internal void check_expr_stmt(CheckerContext *ctx, Ast *node) { } if (do_require) { gbString expr_str = expr_to_string(ce->proc); + defer (gb_string_free(expr_str)); + if (builtin_id) { + String real_name = builtin_procs[builtin_id].name; + if (real_name != make_string(cast(u8 const *)expr_str, gb_string_length(expr_str))) { + error(node, "'%s' ('%.*s.%.*s') requires that its results must be handled", expr_str, + LIT(builtin_proc_pkg_name[builtin_procs[builtin_id].pkg]), LIT(real_name)); + return; + } + } error(node, "'%s' requires that its results must be handled", expr_str); - gb_string_free(expr_str); } return; } else if (expr && expr->kind == Ast_SelectorCallExpr) { diff --git a/src/checker.cpp b/src/checker.cpp index 8f0cc1cd1..852fb89bb 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1479,6 +1479,10 @@ gb_internal Entity *entity_of_node(Ast *expr) { case_ast_node(cc, CaseClause, expr); return cc->implicit_entity; case_end; + + case_ast_node(ce, CallExpr, expr); + return ce->entity_procedure_of; + case_end; } return nullptr; } diff --git a/src/checker.hpp b/src/checker.hpp index 2ac4c8e7a..492a64fb6 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -51,6 +51,12 @@ enum StmtFlag { enum BuiltinProcPkg { BuiltinProcPkg_builtin, BuiltinProcPkg_intrinsics, + BuiltinProcPkg_COUNT +}; + +String builtin_proc_pkg_name[BuiltinProcPkg_COUNT] = { + str_lit("builtin"), + str_lit("intrinsics"), }; struct BuiltinProc { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 5f98bb7b3..35acad42f 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -299,6 +299,8 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc__type_end, + BuiltinProc_procedure_of, + BuiltinProc___entry_point, BuiltinProc_objc_send, @@ -614,6 +616,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, + {STR_LIT("procedure_of"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("__entry_point"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, {STR_LIT("objc_send"), 3, true, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, diff --git a/src/parser.hpp b/src/parser.hpp index 0e411d9ac..02f2af28d 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -458,6 +458,7 @@ AST_KIND(_ExprBegin, "", bool) \ bool optional_ok_one; \ bool was_selector; \ AstSplitArgs *split_args; \ + Entity *entity_procedure_of; \ }) \ AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \ AST_KIND(EnumFieldValue, "enum field value", struct { \ -- cgit v1.2.3 From f57c03c1707f48608bcb3bc87aeee91af60e6d63 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Jun 2024 12:40:29 +0100 Subject: Improve matrix type hinting rules a little --- src/check_expr.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 01cba881e..742909701 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3568,6 +3568,8 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand // prefer the named type x->type = y->type; } + // finish + return; } else { bool is_row_major = xt->Matrix.is_row_major && yt->Matrix.is_row_major; x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count, nullptr, nullptr, is_row_major); -- cgit v1.2.3 From c5f7788652c6f46ae9b1588c8e3638d58c49c92b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Jun 2024 12:54:57 +0100 Subject: Check to see if matrices are exactly the same type --- src/check_expr.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 742909701..0f9bb781e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3564,12 +3564,13 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand x->mode = Addressing_Value; if (are_types_identical(xt, yt)) { + if (are_types_identical(x->type, y->type)) { + return; + } if (!is_type_named(x->type) && is_type_named(y->type)) { // prefer the named type x->type = y->type; } - // finish - return; } else { bool is_row_major = xt->Matrix.is_row_major && yt->Matrix.is_row_major; x->type = alloc_type_matrix(xt->Matrix.elem, xt->Matrix.row_count, yt->Matrix.column_count, nullptr, nullptr, is_row_major); -- cgit v1.2.3 From 33270f14a41a61137351907ccaa5317afbe47ad5 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Wed, 12 Jun 2024 15:31:43 -0400 Subject: Fix #3739 --- src/check_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/check_expr.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 0f9bb781e..359b30276 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2550,7 +2550,7 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast * error_line("\tSuggestion: Did you want to pass the iterable value to the for statement by pointer to get addressable semantics?\n"); } - if (is_type_map(parent_type)) { + if (parent_type != nullptr && is_type_map(parent_type)) { error_line("\t Prefer doing 'for key, &%.*s in ...'\n", LIT(e->token.string)); } else { error_line("\t Prefer doing 'for &%.*s in ...'\n", LIT(e->token.string)); -- cgit v1.2.3