diff options
Diffstat (limited to 'src/checker.cpp')
| -rw-r--r-- | src/checker.cpp | 364 |
1 files changed, 265 insertions, 99 deletions
diff --git a/src/checker.cpp b/src/checker.cpp index 917340a20..244e7efbd 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -224,7 +224,7 @@ gb_internal Scope *create_scope(CheckerInfo *info, Scope *parent) { if (parent != nullptr && parent != builtin_pkg->scope) { Scope *prev_head_child = parent->head_child.exchange(s, std::memory_order_acq_rel); if (prev_head_child) { - prev_head_child->next.store(s, std::memory_order_release); + s->next.store(prev_head_child, std::memory_order_release); } } @@ -313,6 +313,7 @@ gb_internal void add_scope(CheckerContext *c, Ast *node, Scope *scope) { case Ast_StructType: node->StructType.scope = scope; break; case Ast_UnionType: node->UnionType.scope = scope; break; case Ast_EnumType: node->EnumType.scope = scope; break; + case Ast_BitFieldType: node->BitFieldType.scope = scope; break; default: GB_PANIC("Invalid node for add_scope: %.*s", LIT(ast_strings[node->kind])); } } @@ -334,6 +335,7 @@ gb_internal Scope *scope_of_node(Ast *node) { case Ast_StructType: return node->StructType.scope; case Ast_UnionType: return node->UnionType.scope; case Ast_EnumType: return node->EnumType.scope; + case Ast_BitFieldType: return node->BitFieldType.scope; } GB_PANIC("Invalid node for add_scope: %.*s", LIT(ast_strings[node->kind])); return nullptr; @@ -355,6 +357,7 @@ gb_internal void check_open_scope(CheckerContext *c, Ast *node) { case Ast_EnumType: case Ast_UnionType: case Ast_BitSetType: + case Ast_BitFieldType: scope->flags |= ScopeFlag_Type; break; } @@ -700,6 +703,15 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) { array_add(&vetted_entities, ve_unused); } else if (is_shadowed) { array_add(&vetted_entities, ve_shadowed); + } else if (e->kind == Entity_Variable && (e->flags & (EntityFlag_Param|EntityFlag_Using)) == 0) { + i64 sz = type_size_of(e->type); + // TODO(bill): When is a good size warn? + // Is 128 KiB good enough? + if (sz >= 1ll<<17) { + gbString type_str = type_to_string(e->type); + warning(e->token, "Declaration of '%.*s' may cause a stack overflow due to its type '%s' having a size of %lld bytes", LIT(e->token.string), type_str, cast(long long)sz); + gb_string_free(type_str); + } } } rw_mutex_shared_unlock(&scope->mutex); @@ -731,17 +743,6 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) { break; } } - - if (e->kind == Entity_Variable && (e->flags & (EntityFlag_Param|EntityFlag_Using)) == 0) { - i64 sz = type_size_of(e->type); - // TODO(bill): When is a good size warn? - // Is 128 KiB good enough? - if (sz >= 1ll<<17) { - gbString type_str = type_to_string(e->type); - warning(e->token, "Declaration of '%.*s' may cause a stack overflow due to its type '%s' having a size of %lld bytes", LIT(name), type_str, cast(long long)sz); - gb_string_free(type_str); - } - } } array_free(&vetted_entities); @@ -770,15 +771,17 @@ gb_internal void add_type_info_dependency(CheckerInfo *info, DeclInfo *d, Type * rw_mutex_unlock(&d->type_info_deps_mutex); } -gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) { + +gb_internal AstPackage *get_runtime_package(CheckerInfo *info) { + String name = str_lit("runtime"); gbAllocator a = heap_allocator(); - String path = get_fullpath_core(a, name); + String path = get_fullpath_base_collection(a, name, nullptr); defer (gb_free(a, path.text)); auto found = string_map_get(&info->packages, path); if (found == nullptr) { gb_printf_err("Name: %.*s\n", LIT(name)); gb_printf_err("Fullpath: %.*s\n", LIT(path)); - + for (auto const &entry : info->packages) { gb_printf_err("%.*s\n", LIT(entry.key)); } @@ -787,14 +790,37 @@ gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) { return *found; } +gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) { + if (name == "runtime") { + return get_runtime_package(info); + } + + gbAllocator a = heap_allocator(); + String path = get_fullpath_core_collection(a, name, nullptr); + defer (gb_free(a, path.text)); + auto found = string_map_get(&info->packages, path); + if (found == nullptr) { + gb_printf_err("Name: %.*s\n", LIT(name)); + gb_printf_err("Fullpath: %.*s\n", LIT(path)); + + for (auto const &entry : info->packages) { + gb_printf_err("%.*s\n", LIT(entry.key)); + } + GB_ASSERT_MSG(found != nullptr, "Missing core package %.*s", LIT(name)); + } + return *found; +} -gb_internal void add_package_dependency(CheckerContext *c, char const *package_name, char const *name) { +gb_internal void add_package_dependency(CheckerContext *c, char const *package_name, char const *name, bool required=false) { String n = make_string_c(name); AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name)); Entity *e = scope_lookup(p->scope, n); GB_ASSERT_MSG(e != nullptr, "%s", name); GB_ASSERT(c->decl != nullptr); e->flags |= EntityFlag_Used; + if (required) { + e->flags |= EntityFlag_Require; + } add_dependency(c->info, c->decl, e); } @@ -982,6 +1008,7 @@ gb_internal void init_universal(void) { {"Linux", TargetOs_linux}, {"Essence", TargetOs_essence}, {"FreeBSD", TargetOs_freebsd}, + {"Haiku", TargetOs_haiku}, {"OpenBSD", TargetOs_openbsd}, {"WASI", TargetOs_wasi}, {"JS", TargetOs_js}, @@ -1068,24 +1095,43 @@ gb_internal void init_universal(void) { scope_insert(intrinsics_pkg->scope, t_atomic_memory_order->Named.type_name); } - - add_global_bool_constant("ODIN_DEBUG", bc->ODIN_DEBUG); - add_global_bool_constant("ODIN_DISABLE_ASSERT", bc->ODIN_DISABLE_ASSERT); - add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR); - add_global_bool_constant("ODIN_NO_DYNAMIC_LITERALS", bc->no_dynamic_literals); - add_global_bool_constant("ODIN_NO_CRT", bc->no_crt); - add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules); - add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test); - add_global_bool_constant("ODIN_NO_ENTRY_POINT", bc->no_entry_point); - add_global_bool_constant("ODIN_FOREIGN_ERROR_PROCEDURES", bc->ODIN_FOREIGN_ERROR_PROCEDURES); - add_global_bool_constant("ODIN_NO_RTTI", bc->no_rtti); - - add_global_bool_constant("ODIN_VALGRIND_SUPPORT", bc->ODIN_VALGRIND_SUPPORT); - add_global_bool_constant("ODIN_TILDE", bc->tilde_backend); + { + int minimum_os_version = 0; + if (build_context.minimum_os_version_string != "") { + int major, minor, revision = 0; + sscanf(cast(const char *)(build_context.minimum_os_version_string.text), "%d.%d.%d", &major, &minor, &revision); + minimum_os_version = (major*10000)+(minor*100)+revision; + } + add_global_constant("ODIN_MINIMUM_OS_VERSION", t_untyped_integer, exact_value_i64(minimum_os_version)); + } + + add_global_bool_constant("ODIN_DEBUG", bc->ODIN_DEBUG); + add_global_bool_constant("ODIN_DISABLE_ASSERT", bc->ODIN_DISABLE_ASSERT); + add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR); + add_global_bool_constant("ODIN_DEFAULT_TO_PANIC_ALLOCATOR", bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR); + add_global_bool_constant("ODIN_NO_DYNAMIC_LITERALS", bc->no_dynamic_literals); + add_global_bool_constant("ODIN_NO_CRT", bc->no_crt); + add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules); + add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test); + add_global_bool_constant("ODIN_NO_ENTRY_POINT", bc->no_entry_point); + add_global_bool_constant("ODIN_FOREIGN_ERROR_PROCEDURES", bc->ODIN_FOREIGN_ERROR_PROCEDURES); + add_global_bool_constant("ODIN_NO_RTTI", bc->no_rtti); + + add_global_bool_constant("ODIN_VALGRIND_SUPPORT", bc->ODIN_VALGRIND_SUPPORT); + add_global_bool_constant("ODIN_TILDE", bc->tilde_backend); add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp())); - add_global_bool_constant("__ODIN_LLVM_F16_SUPPORTED", lb_use_new_pass_system()); + { + bool f16_supported = lb_use_new_pass_system(); + if (is_arch_wasm()) { + f16_supported = false; + } else if (build_context.metrics.os == TargetOs_darwin && build_context.metrics.arch == TargetArch_amd64) { + // NOTE(laytan): See #3222 for my ramblings on this. + f16_supported = false; + } + add_global_bool_constant("__ODIN_LLVM_F16_SUPPORTED", f16_supported); + } { GlobalEnumValue values[3] = { @@ -1174,7 +1220,7 @@ gb_internal void init_universal(void) { } if (defined_values_double_declaration) { - gb_exit(1); + exit_with_errors(); } @@ -1188,9 +1234,9 @@ gb_internal void init_universal(void) { // intrinsics types for objective-c stuff { - t_objc_object = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_object"), alloc_type_struct()); - t_objc_selector = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_selector"), alloc_type_struct()); - t_objc_class = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_class"), alloc_type_struct()); + t_objc_object = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_object"), alloc_type_struct_complete()); + t_objc_selector = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_selector"), alloc_type_struct_complete()); + t_objc_class = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_class"), alloc_type_struct_complete()); t_objc_id = alloc_type_pointer(t_objc_object); t_objc_SEL = alloc_type_pointer(t_objc_selector); @@ -1231,6 +1277,9 @@ gb_internal void init_checker_info(CheckerInfo *i) { mpsc_init(&i->required_global_variable_queue, a); // 1<<10); mpsc_init(&i->required_foreign_imports_through_force_queue, a); // 1<<10); mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used + + string_map_init(&i->load_directory_cache); + map_init(&i->load_directory_map); } gb_internal void destroy_checker_info(CheckerInfo *i) { @@ -1254,6 +1303,8 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { map_destroy(&i->objc_msgSend_types); string_map_destroy(&i->load_file_cache); + string_map_destroy(&i->load_directory_cache); + map_destroy(&i->load_directory_map); } gb_internal CheckerContext make_checker_context(Checker *c) { @@ -1327,6 +1378,7 @@ gb_internal void init_checker(Checker *c) { array_init(&c->nested_proc_lits, heap_allocator(), 0, 1<<20); mpsc_init(&c->global_untyped_queue, a); // , 1<<20); + mpsc_init(&c->soa_types_to_complete, a); // , 1<<20); c->builtin_ctx = make_checker_context(c); } @@ -1339,6 +1391,7 @@ gb_internal void destroy_checker(Checker *c) { array_free(&c->nested_proc_lits); array_free(&c->procs_to_check); mpsc_destroy(&c->global_untyped_queue); + mpsc_destroy(&c->soa_types_to_complete); } @@ -1638,6 +1691,26 @@ gb_internal bool add_entity_with_name(CheckerContext *c, Scope *scope, Ast *iden } return true; } + +gb_internal bool add_entity_with_name(CheckerInfo *info, Scope *scope, Ast *identifier, Entity *entity, String name) { + if (scope == nullptr) { + return false; + } + + + if (!is_blank_ident(name)) { + Entity *ie = scope_insert(scope, entity); + if (ie != nullptr) { + return redeclaration_error(name, entity, ie); + } + } + if (identifier != nullptr) { + GB_ASSERT(entity->file != nullptr); + add_entity_definition(info, identifier, entity); + } + return true; +} + gb_internal bool add_entity(CheckerContext *c, Scope *scope, Ast *identifier, Entity *entity) { return add_entity_with_name(c, scope, identifier, entity, entity->token.string); } @@ -1962,6 +2035,8 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { break; case Type_Struct: + if (bt->Struct.fields_wait_signal.futex.load() == 0) + return; if (bt->Struct.scope != nullptr) { for (auto const &entry : bt->Struct.scope->elements) { Entity *e = entry.value; @@ -1982,7 +2057,9 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { add_type_info_type_internal(c, bt->Struct.polymorphic_params); for_array(i, bt->Struct.fields) { Entity *f = bt->Struct.fields[i]; - add_type_info_type_internal(c, f->type); + if (f && f->type) { + add_type_info_type_internal(c, f->type); + } } add_comparison_procedures_for_fields(c, bt); break; @@ -2029,6 +2106,12 @@ gb_internal void add_type_info_type_internal(CheckerContext *c, Type *t) { add_type_info_type_internal(c, bt->SoaPointer.elem); break; + case Type_BitField: + add_type_info_type_internal(c, bt->BitField.backing_type); + for (Entity *f : bt->BitField.fields) { + add_type_info_type_internal(c, f->type); + } + break; case Type_Generic: break; @@ -2278,6 +2361,13 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { add_min_dep_type_info(c, bt->SoaPointer.elem); break; + case Type_BitField: + add_min_dep_type_info(c, bt->BitField.backing_type); + for (Entity *f : bt->BitField.fields) { + add_min_dep_type_info(c, f->type); + } + break; + default: GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind])); break; @@ -2345,6 +2435,43 @@ gb_internal void force_add_dependency_entity(Checker *c, Scope *scope, String co add_dependency_to_set(c, e); } +gb_internal void collect_testing_procedures_of_package(Checker *c, AstPackage *pkg) { + AstPackage *testing_package = get_core_package(&c->info, str_lit("testing")); + Scope *testing_scope = testing_package->scope; + Entity *test_signature = scope_lookup_current(testing_scope, str_lit("Test_Signature")); + + Scope *s = pkg->scope; + for (auto const &entry : s->elements) { + Entity *e = entry.value; + if (e->kind != Entity_Procedure) { + continue; + } + + if ((e->flags & EntityFlag_Test) == 0) { + continue; + } + + String name = e->token.string; + + bool is_tester = true; + + Type *t = base_type(e->type); + GB_ASSERT(t->kind == Type_Proc); + if (are_types_identical(t, base_type(test_signature->type))) { + // Good + } else { + gbString str = type_to_string(t); + error(e->token, "Testing procedures must have a signature type of proc(^testing.T), got %s", str); + gb_string_free(str); + is_tester = false; + } + + if (is_tester) { + add_dependency_to_set(c, e); + array_add(&c->info.testing_procedures, e); + } + } +} gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *start) { for_array(i, c->info.definitions) { @@ -2448,41 +2575,13 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st } } - - Entity *test_signature = scope_lookup_current(testing_scope, str_lit("Test_Signature")); - - AstPackage *pkg = c->info.init_package; - Scope *s = pkg->scope; + collect_testing_procedures_of_package(c, pkg); - for (auto const &entry : s->elements) { - Entity *e = entry.value; - if (e->kind != Entity_Procedure) { - continue; - } - - if ((e->flags & EntityFlag_Test) == 0) { - continue; - } - - String name = e->token.string; - - bool is_tester = true; - - Type *t = base_type(e->type); - GB_ASSERT(t->kind == Type_Proc); - if (are_types_identical(t, base_type(test_signature->type))) { - // Good - } else { - gbString str = type_to_string(t); - error(e->token, "Testing procedures must have a signature type of proc(^testing.T), got %s", str); - gb_string_free(str); - is_tester = false; - } - - if (is_tester) { - add_dependency_to_set(c, e); - array_add(&c->info.testing_procedures, e); + if (build_context.test_all_packages) { + for (auto const &entry : c->info.packages) { + AstPackage *pkg = entry.value; + collect_testing_procedures_of_package(c, pkg); } } } else if (start != nullptr) { @@ -2517,13 +2616,11 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { // Odin internal procedures str_lit("__init_context"), - str_lit("cstring_to_string"), + // str_lit("cstring_to_string"), str_lit("_cleanup_runtime"), // Pseudo-CRT required procedures str_lit("memset"), - str_lit("memcpy"), - str_lit("memmove"), // Utility procedures str_lit("memory_equal"), @@ -2531,22 +2628,28 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { str_lit("memory_compare_zero"), ); - FORCE_ADD_RUNTIME_ENTITIES(!build_context.tilde_backend, - // Extended data type internal procedures - str_lit("umodti3"), - str_lit("udivti3"), - str_lit("modti3"), - str_lit("divti3"), - str_lit("fixdfti"), - str_lit("fixunsdfti"), - str_lit("fixunsdfdi"), - str_lit("floattidf"), - str_lit("floattidf_unsigned"), - str_lit("truncsfhf2"), - str_lit("truncdfhf2"), - str_lit("gnu_h2f_ieee"), - str_lit("gnu_f2h_ieee"), - str_lit("extendhfsf2"), + // Only required if no CRT is present + FORCE_ADD_RUNTIME_ENTITIES(build_context.no_crt, + str_lit("memcpy"), + str_lit("memmove"), + ); + + FORCE_ADD_RUNTIME_ENTITIES(is_arch_wasm() && !build_context.tilde_backend, + // // Extended data type internal procedures + // str_lit("umodti3"), + // str_lit("udivti3"), + // str_lit("modti3"), + // str_lit("divti3"), + // str_lit("fixdfti"), + // str_lit("fixunsdfti"), + // str_lit("fixunsdfdi"), + // str_lit("floattidf"), + // str_lit("floattidf_unsigned"), + // str_lit("truncsfhf2"), + // str_lit("truncdfhf2"), + // str_lit("gnu_h2f_ieee"), + // str_lit("gnu_f2h_ieee"), + // str_lit("extendhfsf2"), // WASM Specific str_lit("__ashlti3"), @@ -2863,6 +2966,7 @@ gb_internal void init_core_type_info(Checker *c) { t_type_info_relative_multi_pointer = find_core_type(c, str_lit("Type_Info_Relative_Multi_Pointer")); t_type_info_matrix = find_core_type(c, str_lit("Type_Info_Matrix")); t_type_info_soa_pointer = find_core_type(c, str_lit("Type_Info_Soa_Pointer")); + t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field")); t_type_info_named_ptr = alloc_type_pointer(t_type_info_named); t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer); @@ -2892,6 +2996,7 @@ gb_internal void init_core_type_info(Checker *c) { t_type_info_relative_multi_pointer_ptr = alloc_type_pointer(t_type_info_relative_multi_pointer); t_type_info_matrix_ptr = alloc_type_pointer(t_type_info_matrix); t_type_info_soa_pointer_ptr = alloc_type_pointer(t_type_info_soa_pointer); + t_type_info_bit_field_ptr = alloc_type_pointer(t_type_info_bit_field); } gb_internal void init_mem_allocator(Checker *c) { @@ -2919,6 +3024,16 @@ gb_internal void init_core_source_code_location(Checker *c) { t_source_code_location_ptr = alloc_type_pointer(t_source_code_location); } +gb_internal void init_core_load_directory_file(Checker *c) { + if (t_load_directory_file != nullptr) { + return; + } + t_load_directory_file = find_core_type(c, str_lit("Load_Directory_File")); + t_load_directory_file_ptr = alloc_type_pointer(t_load_directory_file); + t_load_directory_file_slice = alloc_type_slice(t_load_directory_file); +} + + gb_internal void init_core_map_type(Checker *c) { if (t_map_info != nullptr) { return; @@ -3107,6 +3222,7 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { linkage == "link_once") { ac->linkage = linkage; } else { + ERROR_BLOCK(); error(elem, "Invalid linkage '%.*s'. Valid kinds:", LIT(linkage)); error_line("\tinternal\n"); error_line("\tstrong\n"); @@ -3355,6 +3471,7 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { } else if (mode == "speed") { ac->optimization_mode = ProcedureOptimizationMode_Speed; } else { + ERROR_BLOCK(); error(elem, "Invalid optimization_mode for '%.*s'. Valid modes:", LIT(name)); error_line("\tnone\n"); error_line("\tminimal\n"); @@ -3485,6 +3602,7 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) { model == "localexec") { ac->thread_local_model = model; } else { + ERROR_BLOCK(); error(elem, "Invalid thread local model '%.*s'. Valid models:", LIT(model)); error_line("\tdefault\n"); error_line("\tlocaldynamic\n"); @@ -3535,6 +3653,7 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) { linkage == "link_once") { ac->linkage = linkage; } else { + ERROR_BLOCK(); error(elem, "Invalid linkage '%.*s'. Valid kinds:", LIT(linkage)); error_line("\tinternal\n"); error_line("\tstrong\n"); @@ -3589,6 +3708,15 @@ gb_internal DECL_ATTRIBUTE_PROC(const_decl_attribute) { } else if (name == "private") { // NOTE(bill): Handled elsewhere `check_collect_value_decl` return true; + } else if (name == "static" || + name == "thread_local" || + name == "require" || + name == "linkage" || + name == "link_name" || + name == "link_prefix" || + false) { + error(elem, "@(%.*s) is not supported for compile time constant value declarations", LIT(name)); + return true; } return false; } @@ -3689,6 +3817,7 @@ gb_internal void check_decl_attributes(CheckerContext *c, Array<Ast *> const &at if (!proc(c, elem, name, value, ac)) { if (!build_context.ignore_unknown_attributes) { + ERROR_BLOCK(); error(elem, "Unknown attribute element name '%.*s'", LIT(name)); error_line("\tDid you forget to use build flag '-ignore-unknown-attributes'?\n"); } @@ -3758,6 +3887,8 @@ gb_internal bool check_arity_match(CheckerContext *c, AstValueDecl *vd, bool is_ gb_string_free(str); return false; } else if (is_global) { + ERROR_BLOCK(); + Ast *n = vd->values[rhs-1]; error(n, "Expected %td expressions on the right hand side, got %td", lhs, rhs); error_line("Note: Global declarations do not allow for multi-valued expressions"); @@ -3809,6 +3940,7 @@ gb_internal void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array< case Entity_ProcGroup: case Entity_Procedure: case Entity_TypeName: + case Entity_Constant: // Okay break; default: @@ -3976,6 +4108,7 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) { Entity *e = alloc_entity_variable(c->scope, name->Ident.token, nullptr); e->identifier = name; e->file = c->file; + e->Variable.is_global = true; if (entity_visibility_kind != EntityVisiblity_Public) { e->flags |= EntityFlag_NotExported; @@ -4340,6 +4473,10 @@ gb_internal void check_all_global_entities(Checker *c) { DeclInfo *d = e->decl_info; check_single_global_entity(c, e, d); if (e->type != nullptr && is_type_typed(e->type)) { + for (Type *t = nullptr; mpsc_dequeue(&c->soa_types_to_complete, &t); /**/) { + complete_soa_type(c, t, false); + } + (void)type_size_of(e->type); (void)type_align_of(e->type); } @@ -4430,7 +4567,7 @@ gb_internal void add_import_dependency_node(Checker *c, Ast *decl, PtrMap<AstPac if (found == nullptr) { Token token = ast_token(decl); error(token, "Unable to find package: %.*s", LIT(path)); - gb_exit(1); + exit_with_errors(); } AstPackage *pkg = *found; GB_ASSERT(pkg->scope != nullptr); @@ -4551,10 +4688,10 @@ gb_internal Array<ImportPathItem> find_import_path(Checker *c, AstPackage *start continue; } - if (pkg->kind == Package_Runtime) { - // NOTE(bill): Allow cyclic imports within the runtime package for the time being - continue; - } + // if (pkg->kind == Package_Runtime) { + // // NOTE(bill): Allow cyclic imports within the runtime package for the time being + // continue; + // } ImportPathItem item = {pkg, decl}; if (pkg == end) { @@ -4732,6 +4869,22 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { return; } + for (String const &path : fl->fullpaths) { + String ext = path_extension(path); + if (str_eq_ignore_case(ext, ".c") || + str_eq_ignore_case(ext, ".cpp") || + str_eq_ignore_case(ext, ".cxx") || + str_eq_ignore_case(ext, ".h") || + str_eq_ignore_case(ext, ".hpp") || + str_eq_ignore_case(ext, ".hxx") || + false + ) { + error(fl->token, "With 'foreign import', you cannot import a %.*s file directory, you must precompile the library and link against that", LIT(ext)); + break; + } + } + + // if (fl->collection_name != "system") { // char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1); // defer (gb_free(heap_allocator(), c_str)); @@ -4954,7 +5107,7 @@ gb_internal void check_create_file_scopes(Checker *c) { for_array(i, c->parser->packages) { AstPackage *pkg = c->parser->packages[i]; - gb_sort_array(pkg->files.data, pkg->files.count, sort_file_by_name); + array_sort(pkg->files, sort_file_by_name); isize total_pkg_decl_count = 0; for_array(j, pkg->files) { @@ -5358,7 +5511,10 @@ gb_internal void check_procedure_later_from_entity(Checker *c, Entity *e, char c return; } Type *type = base_type(e->type); - GB_ASSERT(type->kind == Type_Proc); + if (type == t_invalid) { + return; + } + GB_ASSERT_MSG(type->kind == Type_Proc, "%s", type_to_string(e->type)); if (is_type_polymorphic(type) && !type->Proc.is_poly_specialized) { return; @@ -5583,7 +5739,7 @@ gb_internal void remove_neighbouring_duplicate_entires_from_sorted_array(Array<E gb_internal void check_test_procedures(Checker *c) { - gb_sort_array(c->info.testing_procedures.data, c->info.testing_procedures.count, init_procedures_cmp); + array_sort(c->info.testing_procedures, init_procedures_cmp); remove_neighbouring_duplicate_entires_from_sorted_array(&c->info.testing_procedures); if (build_context.test_names.entries.count == 0) { @@ -5961,11 +6117,14 @@ gb_internal void check_unique_package_names(Checker *c) { continue; } + + begin_error_block(); error(curr, "Duplicate declaration of 'package %.*s'", LIT(name)); error_line("\tA package name must be unique\n" "\tThere is no relation between a package name and the directory that contains it, so they can be completely different\n" "\tA package name is required for link name prefixing to have a consistent ABI\n"); - error(prev, "found at previous location"); + error_line("%s found at previous location\n", token_pos_to_string(ast_token(prev).pos)); + end_error_block(); } } @@ -5986,6 +6145,9 @@ gb_internal void check_add_definitions_from_queues(Checker *c) { } gb_internal void check_merge_queues_into_arrays(Checker *c) { + for (Type *t = nullptr; mpsc_dequeue(&c->soa_types_to_complete, &t); /**/) { + complete_soa_type(c, t, false); + } check_add_entities_from_queues(c); check_add_definitions_from_queues(c); } @@ -6032,8 +6194,8 @@ gb_internal GB_COMPARE_PROC(fini_procedures_cmp) { } gb_internal void check_sort_init_and_fini_procedures(Checker *c) { - gb_sort_array(c->info.init_procedures.data, c->info.init_procedures.count, init_procedures_cmp); - gb_sort_array(c->info.fini_procedures.data, c->info.fini_procedures.count, fini_procedures_cmp); + array_sort(c->info.init_procedures, init_procedures_cmp); + array_sort(c->info.fini_procedures, fini_procedures_cmp); // NOTE(bill): remove possible duplicates from the init/fini lists // NOTE(bill): because the arrays are sorted, you only need to check the previous element @@ -6196,6 +6358,8 @@ gb_internal void check_parsed_files(Checker *c) { TIME_SECTION("check bodies have all been checked"); check_unchecked_bodies(c); + TIME_SECTION("check #soa types"); + check_merge_queues_into_arrays(c); thread_pool_wait(); @@ -6230,6 +6394,8 @@ gb_internal void check_parsed_files(Checker *c) { error(token, "Undefined entry point procedure 'main'"); } + } else if (build_context.build_mode == BuildMode_DynamicLibrary && build_context.no_entry_point) { + c->info.entry_point = nullptr; } thread_pool_wait(); |