diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 304cf99ac..25e9cb4b0 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -249,9 +249,9 @@ _destroy :: proc(f: ^File_Impl) -> Error { a := f.allocator err0 := free(rawptr(f.wname), a) err1 := delete(f.name, a) - err2 := free(f, a) - err3 := delete(f.r_buf, a) - err4 := delete(f.w_buf, a) + err2 := delete(f.r_buf, a) + err3 := delete(f.w_buf, a) + err4 := free(f, a) err0 or_return err1 or_return err2 or_return diff --git a/core/prof/spall/spall.odin b/core/prof/spall/spall.odin index 16b809359..dc53dc3dc 100644 --- a/core/prof/spall/spall.odin +++ b/core/prof/spall/spall.odin @@ -103,6 +103,7 @@ context_create_with_sleep :: proc(filename: string, sleep := 2 * time.Second) -> context_create :: proc{context_create_with_scale, context_create_with_sleep} +@(no_instrumentation) context_destroy :: proc(ctx: ^Context) { if ctx == nil { return @@ -146,6 +147,7 @@ buffer_flush :: proc "contextless" (ctx: ^Context, buffer: ^Buffer) #no_bounds_c buffer.first_ts = end } +@(no_instrumentation) buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) { buffer_flush(ctx, buffer) @@ -155,12 +157,14 @@ buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) { @(deferred_in=_scoped_buffer_end) +@(no_instrumentation) SCOPED_EVENT :: proc(ctx: ^Context, buffer: ^Buffer, name: string, args: string = "", location := #caller_location) -> bool { _buffer_begin(ctx, buffer, name, args, location) return true } @(private) +@(no_instrumentation) _scoped_buffer_end :: proc(ctx: ^Context, buffer: ^Buffer, _, _: string, _ := #caller_location) { _buffer_end(ctx, buffer) } diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin index 1431442a9..1db32657e 100644 --- a/core/thread/thread_unix.odin +++ b/core/thread/thread_unix.odin @@ -81,8 +81,13 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread { } defer posix.pthread_attr_destroy(&attrs) - // NOTE(tetra, 2019-11-01): These only fail if their argument is invalid. + stacksize: posix.rlimit + if res := posix.getrlimit(.STACK, &stacksize); res == .OK && stacksize.rlim_cur > 0 { + _ = posix.pthread_attr_setstacksize(&attrs, uint(stacksize.rlim_cur)) + } + res: posix.Errno + // NOTE(tetra, 2019-11-01): These only fail if their argument is invalid. res = posix.pthread_attr_setdetachstate(&attrs, .CREATE_JOINABLE) assert(res == nil) when ODIN_OS != .Haiku && ODIN_OS != .NetBSD { diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index da5eb8977..57413f519 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -33,6 +33,7 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool is_type_sliceable, is_type_comparable, is_type_simple_compare, + is_type_nearly_simple_compare, is_type_dereferenceable, is_type_valid_for_keys, is_type_valid_for_matrix_elems, @@ -6159,6 +6160,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_type_is_sliceable: case BuiltinProc_type_is_comparable: case BuiltinProc_type_is_simple_compare: + case BuiltinProc_type_is_nearly_simple_compare: case BuiltinProc_type_is_dereferenceable: case BuiltinProc_type_is_valid_map_key: case BuiltinProc_type_is_valid_matrix_elements: diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 34149f92b..faa338f36 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6621,7 +6621,7 @@ gb_internal bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Sco Entity *e = entry.value; switch (e->kind) { case Entity_TypeName: { - if (print_count == 0) error_line("\n\tWith the following definitions:\n"); + // if (print_count == 0) error_line("\n\tWith the following definitions:\n"); gbString str = type_to_string(e->type); error_line("\t\t%.*s :: %s;\n", LIT(e->token.string), str); diff --git a/src/checker.cpp b/src/checker.cpp index 20da5b19b..e9fa792f3 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -6804,7 +6804,11 @@ gb_internal void check_parsed_files(Checker *c) { for_array(i, c->info.definitions) { Entity *e = c->info.definitions[i]; if (e->kind == Entity_TypeName && e->type != nullptr && is_type_typed(e->type)) { - (void)type_align_of(e->type); + if (e->TypeName.is_type_alias) { + // Ignore for the time being + } else { + (void)type_align_of(e->type); + } } else if (e->kind == Entity_Procedure) { DeclInfo *decl = e->decl_info; ast_node(pl, ProcLit, decl->proc_lit); diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index bff887d9e..b8b105fd2 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -265,6 +265,7 @@ BuiltinProc__type_simple_boolean_begin, BuiltinProc_type_is_sliceable, BuiltinProc_type_is_comparable, BuiltinProc_type_is_simple_compare, // easily compared using memcmp + BuiltinProc_type_is_nearly_simple_compare, // easily compared using memcmp (including floats) BuiltinProc_type_is_dereferenceable, BuiltinProc_type_is_valid_map_key, BuiltinProc_type_is_valid_matrix_elements, @@ -623,6 +624,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_is_sliceable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_comparable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_simple_compare"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_nearly_simple_compare"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_dereferenceable"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_valid_map_key"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_valid_matrix_elements"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/types.cpp b/src/types.cpp index ad576c8af..51d170f2b 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -157,10 +157,11 @@ struct TypeStruct { bool is_polymorphic; bool are_offsets_set : 1; - bool are_offsets_being_processed : 1; bool is_packed : 1; bool is_raw_union : 1; bool is_poly_specialized : 1; + + std::atomic are_offsets_being_processed; }; struct TypeUnion { @@ -259,7 +260,7 @@ struct TypeProc { Slice variables; /* Entity_Variable */ \ i64 * offsets; \ BlockingMutex mutex; /* for settings offsets */ \ - bool are_offsets_being_processed; \ + std::atomic are_offsets_being_processed; \ bool are_offsets_set; \ bool is_packed; \ }) \ @@ -2633,6 +2634,62 @@ gb_internal bool is_type_simple_compare(Type *t) { return false; } +// NOTE(bill): type can be easily compared using memcmp or contains a float +gb_internal bool is_type_nearly_simple_compare(Type *t) { + t = core_type(t); + switch (t->kind) { + case Type_Array: + return is_type_nearly_simple_compare(t->Array.elem); + + case Type_EnumeratedArray: + return is_type_nearly_simple_compare(t->EnumeratedArray.elem); + + case Type_Basic: + if (t->Basic.flags & (BasicFlag_SimpleCompare|BasicFlag_Numeric)) { + return true; + } + if (t->Basic.kind == Basic_typeid) { + return true; + } + return false; + + case Type_Pointer: + case Type_MultiPointer: + case Type_SoaPointer: + case Type_Proc: + case Type_BitSet: + return true; + + case Type_Matrix: + return is_type_nearly_simple_compare(t->Matrix.elem); + + case Type_Struct: + for_array(i, t->Struct.fields) { + Entity *f = t->Struct.fields[i]; + if (!is_type_nearly_simple_compare(f->type)) { + return false; + } + } + return true; + + case Type_Union: + for_array(i, t->Union.variants) { + Type *v = t->Union.variants[i]; + if (!is_type_nearly_simple_compare(v)) { + return false; + } + } + // make it dumb on purpose + return t->Union.variants.count == 1; + + case Type_SimdVector: + return is_type_nearly_simple_compare(t->SimdVector.elem); + + } + + return false; +} + gb_internal bool is_type_load_safe(Type *type) { GB_ASSERT(type != nullptr); type = core_type(core_array_type(type)); @@ -4121,18 +4178,18 @@ gb_internal bool type_set_offsets(Type *t) { if (t->kind == Type_Struct) { MUTEX_GUARD(&t->Struct.offset_mutex); if (!t->Struct.are_offsets_set) { - t->Struct.are_offsets_being_processed = true; + t->Struct.are_offsets_being_processed.store(true); t->Struct.offsets = type_set_offsets_of(t->Struct.fields, t->Struct.is_packed, t->Struct.is_raw_union, t->Struct.custom_min_field_align, t->Struct.custom_max_field_align); - t->Struct.are_offsets_being_processed = false; + t->Struct.are_offsets_being_processed.store(false); t->Struct.are_offsets_set = true; return true; } } else if (is_type_tuple(t)) { MUTEX_GUARD(&t->Tuple.mutex); if (!t->Tuple.are_offsets_set) { - t->Tuple.are_offsets_being_processed = true; + t->Tuple.are_offsets_being_processed.store(true); t->Tuple.offsets = type_set_offsets_of(t->Tuple.variables, t->Tuple.is_packed, false, 1, 0); - t->Tuple.are_offsets_being_processed = false; + t->Tuple.are_offsets_being_processed.store(false); t->Tuple.are_offsets_set = true; return true; } @@ -4317,9 +4374,12 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { if (path->failure) { return FAILURE_SIZE; } - if (t->Struct.are_offsets_being_processed && t->Struct.offsets == nullptr) { - type_path_print_illegal_cycle(path, path->path.count-1); - return FAILURE_SIZE; + { + MUTEX_GUARD(&t->Struct.offset_mutex); + if (t->Struct.are_offsets_being_processed.load() && t->Struct.offsets == nullptr) { + type_path_print_illegal_cycle(path, path->path.count-1); + return FAILURE_SIZE; + } } type_set_offsets(t); GB_ASSERT(t->Struct.fields.count == 0 || t->Struct.offsets != nullptr);