From 39363c401874584e3871caf694f297777a899d2c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 15 Apr 2025 11:50:59 +0100 Subject: Improve name canonization rules for doc writer --- src/name_canonicalization.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/name_canonicalization.cpp') diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index a80dc1996..7db8d107b 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -724,7 +724,11 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { if (is_in_doc_writer()) { type_writer_appendc(w, "$"); type_writer_append(w, type->Generic.name.text, type->Generic.name.len); - type_writer_append_fmt(w, "%lld", cast(long long)type->Generic.id); + type_writer_append_fmt(w, "-%lld", cast(long long)type->Generic.id); + if (type->Generic.specialized) { + type_writer_appendc(w, "/"); + write_type_to_canonical_string(w, type->Generic.specialized); + } } else { GB_PANIC("Type_Generic should never be hit"); } -- cgit v1.2.3 From b2ca76a76a6896ed96ad4e51612b0fb720bc2bc9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 15 Apr 2025 12:07:58 +0100 Subject: Improve name canonicalization rules for the doc writer --- src/name_canonicalization.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'src/name_canonicalization.cpp') diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index 7db8d107b..a6d31b781 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -1,3 +1,5 @@ +gb_internal bool is_in_doc_writer(void); + gb_internal GB_COMPARE_PROC(type_info_pair_cmp) { TypeInfoPair *x = cast(TypeInfoPair *)a; TypeInfoPair *y = cast(TypeInfoPair *)b; @@ -284,6 +286,23 @@ gb_internal void write_canonical_params(TypeWriter *w, Type *params) { } else { write_type_to_canonical_string(w, v->type); } + if (is_in_doc_writer()) { + // NOTE(bill): This just exists to make sure the entities default values exist when + // writing to the odin doc format + Ast *expr = v->Variable.init_expr; + if (expr == nullptr) { + expr = v->Variable.param_value.original_ast_expr; + } + if (expr != nullptr) { + type_writer_appendc(w, "="); + gbString s = write_expr_to_string( // Minor leak + gb_string_make(temporary_allocator(), ""), + expr, + build_context.cmd_doc_flags & CmdDocFlag_Short + ); + type_writer_append(w, s, gb_string_length(s)); + } + } break; case Entity_TypeName: type_writer_appendc(w, CANONICAL_PARAM_TYPEID); @@ -520,7 +539,6 @@ write_base_name: return; } -gb_internal bool is_in_doc_writer(void); // NOTE(bill): This exists so that we deterministically hash a type by serializing it to a canonical string gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { -- cgit v1.2.3 From 6045955c882d6bd68ed96c2ea3662d7811cad6f3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 15 Apr 2025 12:35:20 +0100 Subject: More improvements doc writer name canonicalization --- src/name_canonicalization.cpp | 9 ++++ src/types.cpp | 98 ++++++++++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 33 deletions(-) (limited to 'src/name_canonicalization.cpp') diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index a6d31b781..6aa933e86 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -649,6 +649,10 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { case Type_Union: type_writer_appendc(w, "union"); + if (is_in_doc_writer() && type->Union.polymorphic_params) { + write_canonical_params(w, type->Union.polymorphic_params); + } + switch (type->Union.kind) { case UnionType_no_nil: type_writer_appendc(w, "#no_nil"); break; case UnionType_shared_nil: type_writer_appendc(w, "#shared_nil"); break; @@ -676,6 +680,11 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { } type_writer_appendc(w, "struct"); + + if (is_in_doc_writer() && type->Struct.polymorphic_params) { + write_canonical_params(w, type->Struct.polymorphic_params); + } + if (type->Struct.is_packed) type_writer_appendc(w, "#packed"); if (type->Struct.is_raw_union) type_writer_appendc(w, "#raw_union"); if (type->Struct.is_no_copy) type_writer_appendc(w, "#no_copy"); diff --git a/src/types.cpp b/src/types.cpp index 43fe625f2..48631a373 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -4542,7 +4542,7 @@ gb_internal Type *alloc_type_proc_from_types(Type **param_types, unsigned param_ // return type; // } -gb_internal gbString write_type_to_string(gbString str, Type *type, bool shorthand=false) { +gb_internal gbString write_type_to_string(gbString str, Type *type, bool shorthand=false, bool allow_polymorphic=false) { if (type == nullptr) { return gb_string_appendc(str, ""); } @@ -4567,24 +4567,24 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha str = gb_string_append_length(str, name.text, name.len); if (type->Generic.specialized != nullptr) { str = gb_string_append_rune(str, '/'); - str = write_type_to_string(str, type->Generic.specialized); + str = write_type_to_string(str, type->Generic.specialized, shorthand, allow_polymorphic); } } break; case Type_Pointer: str = gb_string_append_rune(str, '^'); - str = write_type_to_string(str, type->Pointer.elem); + str = write_type_to_string(str, type->Pointer.elem, shorthand, allow_polymorphic); break; case Type_SoaPointer: str = gb_string_appendc(str, "#soa ^"); - str = write_type_to_string(str, type->SoaPointer.elem); + str = write_type_to_string(str, type->SoaPointer.elem, shorthand, allow_polymorphic); break; case Type_MultiPointer: str = gb_string_appendc(str, "[^]"); - str = write_type_to_string(str, type->Pointer.elem); + str = write_type_to_string(str, type->Pointer.elem, shorthand, allow_polymorphic); break; case Type_EnumeratedArray: @@ -4592,31 +4592,31 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha str = gb_string_appendc(str, "#sparse"); } str = gb_string_append_rune(str, '['); - str = write_type_to_string(str, type->EnumeratedArray.index); + str = write_type_to_string(str, type->EnumeratedArray.index, shorthand, allow_polymorphic); str = gb_string_append_rune(str, ']'); - str = write_type_to_string(str, type->EnumeratedArray.elem); + str = write_type_to_string(str, type->EnumeratedArray.elem, shorthand, allow_polymorphic); break; case Type_Array: str = gb_string_appendc(str, gb_bprintf("[%lld]", cast(long long)type->Array.count)); - str = write_type_to_string(str, type->Array.elem); + str = write_type_to_string(str, type->Array.elem, shorthand, allow_polymorphic); break; case Type_Slice: str = gb_string_appendc(str, "[]"); - str = write_type_to_string(str, type->Array.elem); + str = write_type_to_string(str, type->Array.elem, shorthand, allow_polymorphic); break; case Type_DynamicArray: str = gb_string_appendc(str, "[dynamic]"); - str = write_type_to_string(str, type->DynamicArray.elem); + str = write_type_to_string(str, type->DynamicArray.elem, shorthand, allow_polymorphic); break; case Type_Enum: str = gb_string_appendc(str, "enum"); if (type->Enum.base_type != nullptr) { str = gb_string_appendc(str, " "); - str = write_type_to_string(str, type->Enum.base_type); + str = write_type_to_string(str, type->Enum.base_type, shorthand, allow_polymorphic); } str = gb_string_appendc(str, " {"); for_array(i, type->Enum.fields) { @@ -4633,6 +4633,13 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha case Type_Union: str = gb_string_appendc(str, "union"); + + if (allow_polymorphic && type->Struct.polymorphic_params) { + str = gb_string_appendc(str, "("); + str = write_type_to_string(str, type->Struct.polymorphic_params, shorthand, allow_polymorphic); + str = gb_string_appendc(str, ")"); + } + switch (type->Union.kind) { case UnionType_no_nil: str = gb_string_appendc(str, " #no_nil"); break; case UnionType_shared_nil: str = gb_string_appendc(str, " #shared_nil"); break; @@ -4642,7 +4649,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha for_array(i, type->Union.variants) { Type *t = type->Union.variants[i]; if (i > 0) str = gb_string_appendc(str, ", "); - str = write_type_to_string(str, t); + str = write_type_to_string(str, t, shorthand, allow_polymorphic); } str = gb_string_append_rune(str, '}'); break; @@ -4655,17 +4662,24 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha case StructSoa_Dynamic: str = gb_string_appendc(str, "#soa[dynamic]"); break; default: GB_PANIC("Unknown StructSoaKind"); break; } - str = write_type_to_string(str, type->Struct.soa_elem); + str = write_type_to_string(str, type->Struct.soa_elem, shorthand, allow_polymorphic); break; } str = gb_string_appendc(str, "struct"); + + if (allow_polymorphic && type->Struct.polymorphic_params) { + str = gb_string_appendc(str, "("); + str = write_type_to_string(str, type->Struct.polymorphic_params, shorthand, allow_polymorphic); + str = gb_string_appendc(str, ")"); + } + if (type->Struct.is_packed) str = gb_string_appendc(str, " #packed"); if (type->Struct.is_raw_union) str = gb_string_appendc(str, " #raw_union"); if (type->Struct.is_no_copy) str = gb_string_appendc(str, " #no_copy"); if (type->Struct.custom_align != 0) str = gb_string_append_fmt(str, " #align %d", cast(int)type->Struct.custom_align); - str = gb_string_appendc(str, " {"); + str = gb_string_appendc(str, " {"); if (shorthand && type->Struct.fields.count > 16) { str = gb_string_append_fmt(str, "%lld fields...", cast(long long)type->Struct.fields.count); @@ -4678,7 +4692,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha } str = gb_string_append_length(str, f->token.string.text, f->token.string.len); str = gb_string_appendc(str, ": "); - str = write_type_to_string(str, f->type); + str = write_type_to_string(str, f->type, shorthand, allow_polymorphic); } } str = gb_string_append_rune(str, '}'); @@ -4686,9 +4700,9 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha case Type_Map: { str = gb_string_appendc(str, "map["); - str = write_type_to_string(str, type->Map.key); + str = write_type_to_string(str, type->Map.key, shorthand, allow_polymorphic); str = gb_string_append_rune(str, ']'); - str = write_type_to_string(str, type->Map.value); + str = write_type_to_string(str, type->Map.value, shorthand, allow_polymorphic); } break; case Type_Named: @@ -4718,9 +4732,11 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha str = gb_string_append_length(str, name.text, name.len); if (!is_type_untyped(var->type)) { str = gb_string_appendc(str, ": "); - str = write_type_to_string(str, var->type); - str = gb_string_appendc(str, " = "); - str = write_exact_value_to_string(str, var->Constant.value); + str = write_type_to_string(str, var->type, shorthand, allow_polymorphic); + if (var->Constant.value.kind) { + str = gb_string_appendc(str, " = "); + str = write_exact_value_to_string(str, var->Constant.value); + } } else { str = gb_string_appendc(str, " := "); str = write_exact_value_to_string(str, var->Constant.value); @@ -4736,20 +4752,31 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha Type *slice = base_type(var->type); str = gb_string_appendc(str, ".."); GB_ASSERT(var->type->kind == Type_Slice); - str = write_type_to_string(str, slice->Slice.elem); + str = write_type_to_string(str, slice->Slice.elem, shorthand, allow_polymorphic); } else { - str = write_type_to_string(str, var->type); + str = write_type_to_string(str, var->type, shorthand, allow_polymorphic); } } else { GB_ASSERT(var->kind == Entity_TypeName); if (var->type->kind == Type_Generic) { - str = gb_string_appendc(str, "typeid/"); - str = write_type_to_string(str, var->type); + if (var->token.string.len != 0) { + String name = var->token.string; + str = gb_string_appendc(str, "$"); + str = gb_string_append_length(str, name.text, name.len); + str = gb_string_appendc(str, ": typeid"); + if (var->type->Generic.specialized) { + str = gb_string_appendc(str, "/"); + str = write_type_to_string(str, var->type->Generic.specialized, shorthand, allow_polymorphic); + } + } else { + str = gb_string_appendc(str, "typeid/"); + str = write_type_to_string(str, var->type, shorthand, allow_polymorphic); + } } else { str = gb_string_appendc(str, "$"); str = gb_string_append_length(str, name.text, name.len); str = gb_string_appendc(str, "="); - str = write_type_to_string(str, var->type); + str = write_type_to_string(str, var->type, shorthand, allow_polymorphic); } } } @@ -4795,7 +4822,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha } str = gb_string_appendc(str, "("); if (type->Proc.params) { - str = write_type_to_string(str, type->Proc.params); + str = write_type_to_string(str, type->Proc.params, shorthand, allow_polymorphic); } str = gb_string_appendc(str, ")"); if (type->Proc.results) { @@ -4803,7 +4830,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha if (type->Proc.results->Tuple.variables.count > 1) { str = gb_string_appendc(str, "("); } - str = write_type_to_string(str, type->Proc.results); + str = write_type_to_string(str, type->Proc.results, shorthand, allow_polymorphic); if (type->Proc.results->Tuple.variables.count > 1) { str = gb_string_appendc(str, ")"); } @@ -4815,7 +4842,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha if (type->BitSet.elem == nullptr) { str = gb_string_appendc(str, ""); } else if (is_type_enum(type->BitSet.elem)) { - str = write_type_to_string(str, type->BitSet.elem); + str = write_type_to_string(str, type->BitSet.elem, shorthand, allow_polymorphic); } else { str = gb_string_append_fmt(str, "%lld", type->BitSet.lower); str = gb_string_append_fmt(str, "..="); @@ -4823,14 +4850,14 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha } if (type->BitSet.underlying != nullptr) { str = gb_string_appendc(str, "; "); - str = write_type_to_string(str, type->BitSet.underlying); + str = write_type_to_string(str, type->BitSet.underlying, shorthand, allow_polymorphic); } str = gb_string_appendc(str, "]"); break; case Type_SimdVector: str = gb_string_append_fmt(str, "#simd[%d]", cast(int)type->SimdVector.count); - str = write_type_to_string(str, type->SimdVector.elem); + str = write_type_to_string(str, type->SimdVector.elem, shorthand, allow_polymorphic); break; case Type_Matrix: @@ -4838,12 +4865,12 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha str = gb_string_appendc(str, "#row_major "); } str = gb_string_appendc(str, gb_bprintf("matrix[%d, %d]", cast(int)type->Matrix.row_count, cast(int)type->Matrix.column_count)); - str = write_type_to_string(str, type->Matrix.elem); + str = write_type_to_string(str, type->Matrix.elem, shorthand, allow_polymorphic); break; case Type_BitField: str = gb_string_appendc(str, "bit_field "); - str = write_type_to_string(str, type->BitField.backing_type); + str = write_type_to_string(str, type->BitField.backing_type, shorthand, allow_polymorphic); str = gb_string_appendc(str, " {"); for (isize i = 0; i < type->BitField.fields.count; i++) { Entity *f = type->BitField.fields[i]; @@ -4852,7 +4879,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha } str = gb_string_append_length(str, f->token.string.text, f->token.string.len); str = gb_string_appendc(str, ": "); - str = write_type_to_string(str, f->type); + str = write_type_to_string(str, f->type, shorthand, allow_polymorphic); str = gb_string_append_fmt(str, " | %u", type->BitField.bit_sizes[i]); } str = gb_string_appendc(str, " }"); @@ -4870,6 +4897,11 @@ gb_internal gbString type_to_string(Type *type, bool shorthand) { return write_type_to_string(gb_string_make(heap_allocator(), ""), type, shorthand); } +gb_internal gbString type_to_string_polymorphic(Type *type) { + return write_type_to_string(gb_string_make(heap_allocator(), ""), type, false, true); +} + + gb_internal gbString type_to_string_shorthand(Type *type) { return type_to_string(type, true); } -- cgit v1.2.3 From af0e067a12079cc16020e264c6157bb5581c9cf4 Mon Sep 17 00:00:00 2001 From: bogwi Date: Mon, 5 May 2025 15:14:06 +0900 Subject: CHECK 2 done Add support for handling generic types in LLVM backend - Updated `lb_type_internal` to return a pointer type for unspecialized generics. - Modified `write_type_to_canonical_string` to handle specialized generics without panicking. - Enhanced `default_type` to return the default type of specialized generics when applicable. --- src/llvm_backend_general.cpp | 8 ++++++++ src/name_canonicalization.cpp | 6 +++++- src/types.cpp | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src/name_canonicalization.cpp') diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 41a6fb34a..4b9b8d45f 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2212,6 +2212,14 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { case Type_BitField: return lb_type_internal(m, type->BitField.backing_type); + + case Type_Generic: + if (type->Generic.specialized) { + return lb_type_internal(m, type->Generic.specialized); + } else { + // For unspecialized generics, use a pointer type as a placeholder + return LLVMPointerType(LLVMInt8TypeInContext(m->ctx), 0); + } } GB_PANIC("Invalid type %s", type_to_string(type)); diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index 6aa933e86..0372f5039 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -756,8 +756,12 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { type_writer_appendc(w, "/"); write_type_to_canonical_string(w, type->Generic.specialized); } + } else if (type->Generic.specialized) { + // If we have a specialized type, use that instead of panicking + write_type_to_canonical_string(w, type->Generic.specialized); } else { - GB_PANIC("Type_Generic should never be hit"); + // For unspecialized generics, use a generic placeholder string + type_writer_appendc(w, "rawptr"); } return; diff --git a/src/types.cpp b/src/types.cpp index 9c9472a28..cd33f1a0f 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2932,6 +2932,10 @@ gb_internal Type *default_type(Type *type) { case Basic_UntypedString: return t_string; case Basic_UntypedRune: return t_rune; } + } else if (type->kind == Type_Generic) { + if (type->Generic.specialized) { + return default_type(type->Generic.specialized); + } } return type; } -- cgit v1.2.3 From 7057fc8dfc960ad3e7ea4f76deeaafd0cdcf4cf6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 30 Jul 2025 23:14:29 +0100 Subject: Remove the semantics of `#no_copy`, keep the grammar --- base/runtime/core.odin | 2 +- src/check_decl.cpp | 7 ------- src/check_expr.cpp | 23 ----------------------- src/check_stmt.cpp | 2 -- src/check_type.cpp | 1 - src/llvm_backend_type.cpp | 2 +- src/name_canonicalization.cpp | 1 - src/types.cpp | 7 ------- 8 files changed, 2 insertions(+), 43 deletions(-) (limited to 'src/name_canonicalization.cpp') diff --git a/base/runtime/core.odin b/base/runtime/core.odin index 090d1a65b..baecb4146 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -115,7 +115,7 @@ Type_Info_Struct_Flags :: distinct bit_set[Type_Info_Struct_Flag; u8] Type_Info_Struct_Flag :: enum u8 { packed = 0, raw_union = 1, - no_copy = 2, + _ = 2, align = 3, } diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 0bacf891b..dd4c09e85 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -145,13 +145,6 @@ gb_internal void check_init_variables(CheckerContext *ctx, Entity **lhs, isize l if (d != nullptr) { d->init_expr = o->expr; } - - if (o->type && is_type_no_copy(o->type)) { - ERROR_BLOCK(); - if (check_no_copy_assignment(*o, str_lit("initialization"))) { - error_line("\tInitialization of a #no_copy type must be either implicitly zero, a constant literal, or a return value from a call expression"); - } - } } if (rhs_count > 0 && lhs_count != rhs_count) { error(lhs[0]->token, "Assignment count mismatch '%td' = '%td'", lhs_count, rhs_count); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index dd6a89e5b..6723a7580 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5763,22 +5763,6 @@ gb_internal bool check_identifier_exists(Scope *s, Ast *node, bool nested = fals return false; } -gb_internal bool check_no_copy_assignment(Operand const &o, String const &context) { - if (o.type && is_type_no_copy(o.type)) { - Ast *expr = unparen_expr(o.expr); - if (expr && o.mode != Addressing_Constant && o.mode != Addressing_Type) { - if (expr->kind == Ast_CallExpr) { - // Okay - } else { - error(o.expr, "Invalid use of #no_copy value in %.*s", LIT(context)); - return true; - } - } - } - return false; -} - - gb_internal bool check_assignment_arguments(CheckerContext *ctx, Array const &lhs, Array *operands, Slice const &rhs) { bool optional_ok = false; isize tuple_index = 0; @@ -5849,7 +5833,6 @@ gb_internal bool check_assignment_arguments(CheckerContext *ctx, Array for (Entity *e : tuple->variables) { o.type = e->type; array_add(operands, o); - check_no_copy_assignment(o, str_lit("assignment")); } tuple_index += tuple->variables.count; @@ -6236,12 +6219,6 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A } - for (Operand const &o : ordered_operands) { - if (o.mode != Addressing_Invalid) { - check_no_copy_assignment(o, str_lit("procedure call expression")); - } - } - for (isize i = 0; i < pt->param_count; i++) { if (!visited[i]) { Entity *e = pt->params->Tuple.variables[i]; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 7187d95b3..bc9b6c5dd 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -430,8 +430,6 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O Ast *node = unparen_expr(lhs->expr); - check_no_copy_assignment(*rhs, context_name); - // NOTE(bill): Ignore assignments to '_' if (is_blank_ident(node)) { check_assignment(ctx, rhs, nullptr, str_lit("assignment to '_' identifier")); diff --git a/src/check_type.cpp b/src/check_type.cpp index 5f9540ee0..79705b928 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -646,7 +646,6 @@ gb_internal void check_struct_type(CheckerContext *ctx, Type *struct_type, Ast * struct_type->Struct.node = node; struct_type->Struct.scope = ctx->scope; struct_type->Struct.is_packed = st->is_packed; - struct_type->Struct.is_no_copy = st->is_no_copy; struct_type->Struct.polymorphic_params = check_record_polymorphic_params( ctx, st->polymorphic_params, &struct_type->Struct.is_polymorphic, diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 4e514c3d1..43c5f0b40 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -797,7 +797,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ u8 flags = 0; if (t->Struct.is_packed) flags |= 1<<0; if (t->Struct.is_raw_union) flags |= 1<<1; - if (t->Struct.is_no_copy) flags |= 1<<2; + // if (t->Struct.custom_align) flags |= 1<<3; vals[6] = lb_const_int(m, t_u8, flags).value; diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index 0372f5039..e3090368a 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -687,7 +687,6 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { if (type->Struct.is_packed) type_writer_appendc(w, "#packed"); if (type->Struct.is_raw_union) type_writer_appendc(w, "#raw_union"); - if (type->Struct.is_no_copy) type_writer_appendc(w, "#no_copy"); if (type->Struct.custom_min_field_align != 0) type_writer_append_fmt(w, "#min_field_align(%lld)", cast(long long)type->Struct.custom_min_field_align); if (type->Struct.custom_max_field_align != 0) type_writer_append_fmt(w, "#max_field_align(%lld)", cast(long long)type->Struct.custom_max_field_align); if (type->Struct.custom_align != 0) type_writer_append_fmt(w, "#align(%lld)", cast(long long)type->Struct.custom_align); diff --git a/src/types.cpp b/src/types.cpp index 74da7f6aa..2e696810d 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -155,7 +155,6 @@ struct TypeStruct { bool are_offsets_being_processed : 1; bool is_packed : 1; bool is_raw_union : 1; - bool is_no_copy : 1; bool is_poly_specialized : 1; }; @@ -1780,10 +1779,6 @@ gb_internal bool is_type_raw_union(Type *t) { t = base_type(t); return (t->kind == Type_Struct && t->Struct.is_raw_union); } -gb_internal bool is_type_no_copy(Type *t) { - t = base_type(t); - return (t->kind == Type_Struct && t->Struct.is_no_copy); -} gb_internal bool is_type_enum(Type *t) { t = base_type(t); return (t->kind == Type_Enum); @@ -2859,7 +2854,6 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple case Type_Struct: if (x->Struct.is_raw_union == y->Struct.is_raw_union && - x->Struct.is_no_copy == y->Struct.is_no_copy && x->Struct.fields.count == y->Struct.fields.count && x->Struct.is_packed == y->Struct.is_packed && x->Struct.soa_kind == y->Struct.soa_kind && @@ -4832,7 +4826,6 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha if (type->Struct.is_packed) str = gb_string_appendc(str, " #packed"); if (type->Struct.is_raw_union) str = gb_string_appendc(str, " #raw_union"); - if (type->Struct.is_no_copy) str = gb_string_appendc(str, " #no_copy"); if (type->Struct.custom_align != 0) str = gb_string_append_fmt(str, " #align %d", cast(int)type->Struct.custom_align); str = gb_string_appendc(str, " {"); -- cgit v1.2.3 From ecb6b35da561bfdaf89c0d39865a93abc26c3ad0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Aug 2025 15:29:53 +0100 Subject: Fix name canonicalization for named specialized forms --- src/name_canonicalization.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/name_canonicalization.cpp') diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index e3090368a..6a4538e26 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -505,7 +505,13 @@ write_base_name: Type *params = nullptr; Entity *parent = type_get_polymorphic_parent(e->type, ¶ms); - if (parent && (parent->token.string == e->token.string)) { + if (parent && (e->token.string == parent->token.string)) { + // Check for `distinct` forms + type_writer_append(w, parent->token.string.text, parent->token.string.len); + write_canonical_params(w, params); + } else if (parent && string_starts_with(e->token.string, parent->token.string) && + string_contains_char(e->token.string, '(')) { + // Check for named specialization forms type_writer_append(w, parent->token.string.text, parent->token.string.len); write_canonical_params(w, params); } else { @@ -767,7 +773,6 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { case Type_Named: if (type->Named.type_name != nullptr) { write_canonical_entity_name(w, type->Named.type_name); - return; } else { type_writer_append(w, type->Named.name.text, type->Named.name.len); } -- cgit v1.2.3 From 1e0902677f905e752b42e2f48dcda53141b78eee Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 10 Sep 2025 17:29:11 +0100 Subject: Multithread min dep set by removing the set itself --- src/checker.cpp | 193 ++++++++++++++++++++++-------------------- src/checker.hpp | 7 +- src/entity.cpp | 1 + src/error.cpp | 16 ++-- src/llvm_backend.cpp | 17 ++-- src/llvm_backend_proc.cpp | 3 +- src/llvm_backend_stmt.cpp | 6 +- src/main.cpp | 3 +- src/name_canonicalization.cpp | 61 ++++++++++++- src/name_canonicalization.hpp | 2 + src/ptr_set.cpp | 38 +++++++++ src/threading.cpp | 38 +++++++++ src/types.cpp | 1 + 13 files changed, 263 insertions(+), 123 deletions(-) (limited to 'src/name_canonicalization.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 26430359c..b3a702cbd 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1712,7 +1712,7 @@ gb_internal void check_remove_expr_info(CheckerContext *c, Ast *e) { } gb_internal isize type_info_index(CheckerInfo *info, TypeInfoPair pair, bool error_on_failure) { - mutex_lock(&info->minimum_dependency_type_info_mutex); + rw_mutex_shared_lock(&info->minimum_dependency_type_info_mutex); isize entry_index = -1; u64 hash = pair.hash; @@ -1720,7 +1720,7 @@ gb_internal isize type_info_index(CheckerInfo *info, TypeInfoPair pair, bool err if (found_entry_index) { entry_index = *found_entry_index; } - mutex_unlock(&info->minimum_dependency_type_info_mutex); + rw_mutex_shared_unlock(&info->minimum_dependency_type_info_mutex); if (error_on_failure && entry_index < 0) { compiler_error("Type_Info for '%s' could not be found", type_to_string(pair.type)); @@ -2377,11 +2377,8 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { return; } - { - MUTEX_GUARD(&c->info.minimum_dependency_type_info_mutex); - if (type_set_update(&c->info.min_dep_type_info_set, t)) { - return; - } + if (type_set_update_with_mutex(&c->info.min_dep_type_info_set, t, &c->info.min_dep_type_info_set_mutex)) { + return; } // Add nested types @@ -2555,13 +2552,15 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) { } } +gb_internal void add_dependency_to_set_threaded(Checker *c, Entity *entity); + +gb_global std::atomic global_checker_ptr; + gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { if (entity == nullptr) { return; } - CheckerInfo *info = &c->info; - if (entity->type != nullptr && is_type_polymorphic(entity->type)) { DeclInfo *decl = decl_info_of_entity(entity); @@ -2570,11 +2569,8 @@ gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { } } - { - MUTEX_GUARD(&info->minimum_dependency_type_info_mutex); - if (ptr_set_update(&info->minimum_dependency_set, entity)) { - return; - } + if (entity->min_dep_count.fetch_add(1, std::memory_order_relaxed) > 0) { + return; } DeclInfo *decl = decl_info_of_entity(entity); @@ -2584,46 +2580,45 @@ gb_internal void add_dependency_to_set(Checker *c, Entity *entity) { for (TypeInfoPair const tt : decl->type_info_deps) { add_min_dep_type_info(c, tt.type); } - for (Entity *e : decl->deps) { - add_dependency_to_set(c, e); - if (e->kind == Entity_Procedure && e->Procedure.is_foreign) { - Entity *fl = e->Procedure.foreign_library; - if (fl != nullptr) { - GB_ASSERT_MSG(fl->kind == Entity_LibraryName && - (fl->flags&EntityFlag_Used), - "%.*s", LIT(entity->token.string)); - add_dependency_to_set(c, fl); + switch (e->kind) { + case Entity_Procedure: + if (e->Procedure.is_foreign) { + Entity *fl = e->Procedure.foreign_library; + if (fl != nullptr) { + GB_ASSERT_MSG(fl->kind == Entity_LibraryName && + (fl->flags&EntityFlag_Used), + "%.*s", LIT(entity->token.string)); + add_dependency_to_set(c, fl); + } } - } else if (e->kind == Entity_Variable && e->Variable.is_foreign) { - Entity *fl = e->Variable.foreign_library; - if (fl != nullptr) { - GB_ASSERT_MSG(fl->kind == Entity_LibraryName && - (fl->flags&EntityFlag_Used), - "%.*s", LIT(entity->token.string)); - add_dependency_to_set(c, fl); + break; + case Entity_Variable: + if (e->Variable.is_foreign) { + Entity *fl = e->Variable.foreign_library; + if (fl != nullptr) { + GB_ASSERT_MSG(fl->kind == Entity_LibraryName && + (fl->flags&EntityFlag_Used), + "%.*s", LIT(entity->token.string)); + add_dependency_to_set(c, fl); + } } + break; } } -} -struct AddDependecyToSetWorkerData { - Checker *c; - Entity *entity; -}; - -gb_internal void add_dependency_to_set_threaded(Checker *c, Entity *entity); + for (Entity *e : decl->deps) { + add_dependency_to_set(c, e); + } +} gb_internal WORKER_TASK_PROC(add_dependency_to_set_worker) { - AddDependecyToSetWorkerData *wd = cast(AddDependecyToSetWorkerData *)data; - Checker *c = wd->c; - Entity *entity = wd->entity; + Checker *c = global_checker_ptr.load(std::memory_order_relaxed); + Entity *entity = cast(Entity *)data; if (entity == nullptr) { return 0; } - CheckerInfo *info = &c->info; - if (entity->type != nullptr && is_type_polymorphic(entity->type)) { DeclInfo *decl = decl_info_of_entity(entity); @@ -2632,11 +2627,8 @@ gb_internal WORKER_TASK_PROC(add_dependency_to_set_worker) { } } - { - MUTEX_GUARD(&info->minimum_dependency_type_info_mutex); - if (ptr_set_update(&info->minimum_dependency_set, entity)) { - return 0; - } + if (entity->min_dep_count.fetch_add(1, std::memory_order_relaxed) > 0) { + return 0; } DeclInfo *decl = decl_info_of_entity(entity); @@ -2648,25 +2640,36 @@ gb_internal WORKER_TASK_PROC(add_dependency_to_set_worker) { } for (Entity *e : decl->deps) { - add_dependency_to_set(c, e); - if (e->kind == Entity_Procedure && e->Procedure.is_foreign) { - Entity *fl = e->Procedure.foreign_library; - if (fl != nullptr) { - GB_ASSERT_MSG(fl->kind == Entity_LibraryName && - (fl->flags&EntityFlag_Used), - "%.*s", LIT(entity->token.string)); - add_dependency_to_set_threaded(c, fl); + switch (e->kind) { + case Entity_Procedure: + if (e->Procedure.is_foreign) { + Entity *fl = e->Procedure.foreign_library; + if (fl != nullptr) { + GB_ASSERT_MSG(fl->kind == Entity_LibraryName && + (fl->flags&EntityFlag_Used), + "%.*s", LIT(entity->token.string)); + add_dependency_to_set_threaded(c, fl); + } } - } else if (e->kind == Entity_Variable && e->Variable.is_foreign) { - Entity *fl = e->Variable.foreign_library; - if (fl != nullptr) { - GB_ASSERT_MSG(fl->kind == Entity_LibraryName && - (fl->flags&EntityFlag_Used), - "%.*s", LIT(entity->token.string)); - add_dependency_to_set_threaded(c, fl); + break; + case Entity_Variable: + if (e->Variable.is_foreign) { + Entity *fl = e->Variable.foreign_library; + if (fl != nullptr) { + GB_ASSERT_MSG(fl->kind == Entity_LibraryName && + (fl->flags&EntityFlag_Used), + "%.*s", LIT(entity->token.string)); + add_dependency_to_set_threaded(c, fl); + } } + break; } } + + for (Entity *e : decl->deps) { + add_dependency_to_set_threaded(c, e); + } + return 0; } @@ -2675,11 +2678,7 @@ gb_internal void add_dependency_to_set_threaded(Checker *c, Entity *entity) { if (entity == nullptr) { return; } - - AddDependecyToSetWorkerData *wd = gb_alloc_item(temporary_allocator(), AddDependecyToSetWorkerData); - wd->c = c; - wd->entity = entity; - thread_pool_add_task(add_dependency_to_set_worker, wd); + thread_pool_add_task(add_dependency_to_set_worker, entity); } @@ -2732,27 +2731,35 @@ gb_internal void collect_testing_procedures_of_package(Checker *c, AstPackage *p } gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *start) { + // auto const &add_to_set = add_dependency_to_set; + auto const &add_to_set = add_dependency_to_set_threaded; + + Scope *builtin_scope = builtin_pkg->scope; for_array(i, c->info.definitions) { Entity *e = c->info.definitions[i]; - if (e->scope == builtin_pkg->scope) { + if (e->scope == builtin_scope) { if (e->type == nullptr) { - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); + } + } else if (e->kind == Entity_Procedure) { + if (e->Procedure.is_export) { + add_to_set(c, e); + } + } else if (e->kind == Entity_Variable) { + if (e->Variable.is_export) { + add_to_set(c, e); } - } else if (e->kind == Entity_Procedure && e->Procedure.is_export) { - add_dependency_to_set_threaded(c, e); - } else if (e->kind == Entity_Variable && e->Variable.is_export) { - add_dependency_to_set_threaded(c, e); } } for (Entity *e; mpsc_dequeue(&c->info.required_foreign_imports_through_force_queue, &e); /**/) { array_add(&c->info.required_foreign_imports_through_force, e); - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); } for (Entity *e; mpsc_dequeue(&c->info.required_global_variable_queue, &e); /**/) { e->flags |= EntityFlag_Used; - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); } for_array(i, c->info.entities) { @@ -2760,16 +2767,16 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st switch (e->kind) { case Entity_Variable: if (e->Variable.is_export) { - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); } else if (e->flags & EntityFlag_Require) { - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); } break; case Entity_Procedure: if (e->Procedure.is_export) { - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); } else if (e->flags & EntityFlag_Require) { - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); } if (e->flags & EntityFlag_Init) { Type *t = base_type(e->type); @@ -2809,7 +2816,7 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st if (is_init) { - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); array_add(&c->info.init_procedures, e); } } else if (e->flags & EntityFlag_Fini) { @@ -2844,7 +2851,7 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st } if (is_fini) { - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); array_add(&c->info.fini_procedures, e); } } @@ -2861,7 +2868,7 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st Entity *e = entry.value; if (e != nullptr) { e->flags |= EntityFlag_Used; - add_dependency_to_set_threaded(c, e); + add_to_set(c, e); } } @@ -2876,16 +2883,11 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st } } else if (start != nullptr) { start->flags |= EntityFlag_Used; - add_dependency_to_set_threaded(c, start); + add_to_set(c, start); } } gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { - isize entity_count = c->info.entities.count; - isize min_dep_set_cap = next_pow2_isize(entity_count*4); // empirically determined factor - - ptr_set_init(&c->info.minimum_dependency_set, min_dep_set_cap); - #define FORCE_ADD_RUNTIME_ENTITIES(condition, ...) do { \ if (condition) { \ String entities[] = {__VA_ARGS__}; \ @@ -6267,8 +6269,10 @@ gb_internal void check_unchecked_bodies(Checker *c) { // use the `procs_to_check` array global_procedure_body_in_worker_queue = false; - for (Entity *e : c->info.minimum_dependency_set) { - check_procedure_later_from_entity(c, e, "check_unchecked_bodies"); + for (Entity *e : c->info.entities) { + if (e->min_dep_count.load(std::memory_order_relaxed) > 0) { + check_procedure_later_from_entity(c, e, "check_unchecked_bodies"); + } } if (!global_procedure_body_in_worker_queue) { @@ -7042,6 +7046,7 @@ gb_internal void check_merge_queues_into_arrays(Checker *c) { } check_add_entities_from_queues(c); check_add_definitions_from_queues(c); + thread_pool_wait(); } gb_internal GB_COMPARE_PROC(init_procedures_cmp) { @@ -7100,7 +7105,7 @@ gb_internal void add_type_info_for_type_definitions(Checker *c) { Entity *e = c->info.definitions[i]; if (e->kind == Entity_TypeName && e->type != nullptr && is_type_typed(e->type)) { i64 align = type_align_of(e->type); - if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) { + if (align > 0 && e->min_dep_count.load(std::memory_order_relaxed) > 0) { add_type_info_type(&c->builtin_ctx, e->type); } } @@ -7170,6 +7175,8 @@ gb_internal void check_update_dependency_tree_for_procedures(Checker *c) { gb_internal void check_parsed_files(Checker *c) { + global_checker_ptr.store(c, std::memory_order_relaxed); + TIME_SECTION("map full filepaths to scope"); add_type_info_type(&c->builtin_ctx, t_invalid); @@ -7312,11 +7319,9 @@ gb_internal void check_parsed_files(Checker *c) { check_unchecked_bodies(c); TIME_SECTION("check #soa types"); - check_merge_queues_into_arrays(c); - thread_pool_wait(); - TIME_SECTION("update minimum dependency set"); + TIME_SECTION("update minimum dependency set again"); generate_minimum_dependency_set_internal(c, c->info.entry_point); // NOTE(laytan): has to be ran after generate_minimum_dependency_set, diff --git a/src/checker.hpp b/src/checker.hpp index 1da46b74a..8b4d61ee2 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -449,11 +449,10 @@ struct CheckerInfo { Scope * init_scope; Entity * entry_point; - BlockingMutex minimum_dependency_set_mutex; - PtrSet minimum_dependency_set; - - BlockingMutex minimum_dependency_type_info_mutex; + RwMutex minimum_dependency_type_info_mutex; PtrMap min_dep_type_info_index_map; + + RWSpinLock min_dep_type_info_set_mutex; TypeSet min_dep_type_info_set; Array type_info_types_hash_map; // 2 * type_info_types.count diff --git a/src/entity.cpp b/src/entity.cpp index 6c0aa6ace..5ca3fa916 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -164,6 +164,7 @@ struct Entity { u64 id; std::atomic flags; std::atomic state; + std::atomic min_dep_count; Token token; Scope * scope; Type * type; diff --git a/src/error.cpp b/src/error.cpp index 006d5ae8d..10bf1caf5 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -86,7 +86,7 @@ gb_internal char *token_pos_to_string(TokenPos const &pos); gb_internal bool set_file_path_string(i32 index, String const &path) { bool ok = false; GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.path_mutex); + // mutex_lock(&global_error_collector.path_mutex); mutex_lock(&global_files_mutex); if (index >= global_file_path_strings.count) { @@ -99,14 +99,14 @@ gb_internal bool set_file_path_string(i32 index, String const &path) { } mutex_unlock(&global_files_mutex); - mutex_unlock(&global_error_collector.path_mutex); + // mutex_unlock(&global_error_collector.path_mutex); return ok; } gb_internal bool thread_safe_set_ast_file_from_id(i32 index, AstFile *file) { bool ok = false; GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.path_mutex); + // mutex_lock(&global_error_collector.path_mutex); mutex_lock(&global_files_mutex); if (index >= global_files.count) { @@ -118,13 +118,13 @@ gb_internal bool thread_safe_set_ast_file_from_id(i32 index, AstFile *file) { ok = true; } mutex_unlock(&global_files_mutex); - mutex_unlock(&global_error_collector.path_mutex); + // mutex_unlock(&global_error_collector.path_mutex); return ok; } gb_internal String get_file_path_string(i32 index) { GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.path_mutex); + // mutex_lock(&global_error_collector.path_mutex); mutex_lock(&global_files_mutex); String path = {}; @@ -133,13 +133,13 @@ gb_internal String get_file_path_string(i32 index) { } mutex_unlock(&global_files_mutex); - mutex_unlock(&global_error_collector.path_mutex); + // mutex_unlock(&global_error_collector.path_mutex); return path; } gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) { GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.path_mutex); + // mutex_lock(&global_error_collector.path_mutex); mutex_lock(&global_files_mutex); AstFile *file = nullptr; @@ -148,7 +148,7 @@ gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) { } mutex_unlock(&global_files_mutex); - mutex_unlock(&global_error_collector.path_mutex); + // mutex_unlock(&global_error_collector.path_mutex); return file; } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index ff17e9c10..11b979774 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2097,8 +2097,6 @@ gb_internal GB_COMPARE_PROC(llvm_global_entity_cmp) { } gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, CheckerInfo *info, bool do_threading) { - auto *min_dep_set = &info->minimum_dependency_set; - for (Entity *e : info->entities) { String name = e->token.string; Scope * scope = e->scope; @@ -2135,11 +2133,16 @@ gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, Checker } } - if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) { + if (!polymorphic_struct && e->min_dep_count.load(std::memory_order_relaxed) == 0) { // NOTE(bill): Nothing depends upon it so doesn't need to be built continue; } + // if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) { + // // NOTE(bill): Nothing depends upon it so doesn't need to be built + // continue; + // } + lbModule *m = &gen->default_module; if (USE_SEPARATE_MODULES) { m = lb_module_of_entity(gen, e); @@ -2845,8 +2848,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { lbModule *default_module = &gen->default_module; CheckerInfo *info = gen->info; - auto *min_dep_set = &info->minimum_dependency_set; - switch (build_context.metrics.arch) { case TargetArch_amd64: case TargetArch_i386: @@ -3184,10 +3185,14 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { continue; } - if (!ptr_set_exists(min_dep_set, e)) { + if (e->min_dep_count.load(std::memory_order_relaxed) == 0) { continue; } + // if (!ptr_set_exists(min_dep_set, e)) { + // continue; + // } + DeclInfo *decl = decl_info_of_entity(e); if (decl == nullptr) { continue; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index f2e6662c8..06829efab 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -798,9 +798,8 @@ gb_internal void lb_end_procedure_body(lbProcedure *p) { gb_internal void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e) { GB_ASSERT(pd->body != nullptr); lbModule *m = p->module; - auto *min_dep_set = &m->info->minimum_dependency_set; - if (ptr_set_exists(min_dep_set, e) == false) { + if (e->min_dep_count.load(std::memory_order_relaxed) == 0) { // NOTE(bill): Nothing depends upon it so doesn't need to be built return; } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 5481ca447..590920b59 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -3,8 +3,6 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) return; } - auto *min_dep_set = &p->module->info->minimum_dependency_set; - for (Ast *ident : vd->names) { GB_ASSERT(ident->kind == Ast_Ident); Entity *e = entity_of_node(ident); @@ -21,7 +19,7 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) } } - if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) { + if (!polymorphic_struct && e->min_dep_count.load(std::memory_order_relaxed) == 0) { continue; } @@ -56,7 +54,7 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) if (gpd) { rw_mutex_shared_lock(&gpd->mutex); for (Entity *e : gpd->procs) { - if (!ptr_set_exists(min_dep_set, e)) { + if (e->min_dep_count.load(std::memory_order_relaxed) == 0) { continue; } DeclInfo *d = decl_info_of_entity(e); diff --git a/src/main.cpp b/src/main.cpp index db4dee080..184b1eaac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3050,7 +3050,8 @@ gb_internal void print_show_unused(Checker *c) { if (e->token.string == "_") { continue; } - if (ptr_set_exists(&info->minimum_dependency_set, e)) { + + if (e->min_dep_count.load(std::memory_order_relaxed) > 0) { continue; } array_add(&unused, e); diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index 6a4538e26..8bacfabc6 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -57,10 +57,13 @@ gb_internal isize type_set__find(TypeSet *s, TypeInfoPair pair) { usize mask = s->capacity-1; usize hash_index = cast(usize)hash & mask; for (usize i = 0; i < s->capacity; i++) { - Type *key = s->keys[hash_index].type; - if (are_types_identical_unique_tuples(key, pair.type)) { + auto *e = &s->keys[hash_index]; + u64 hash = e->hash; + Type *key = e->type; + if (hash == pair.hash && + are_types_identical_unique_tuples(key, pair.type)) { return hash_index; - } else if (key == 0) { + } else if (key == nullptr) { return -1; } hash_index = (hash_index+1)&mask; @@ -164,6 +167,48 @@ gb_internal bool type_set_update(TypeSet *s, Type *ptr) { // returns true if it return type_set_update(s, pair); } +gb_internal bool type_set_update_with_mutex(TypeSet *s, TypeInfoPair pair, RWSpinLock *m) { // returns true if it previously existsed + rwlock_acquire_upgrade(m); + if (type_set_exists(s, pair)) { + rwlock_release_upgrade(m); + return true; + } + + rwlock_release_upgrade_and_acquire_write(m); + defer (rwlock_release_write(m)); + + if (s->keys == nullptr) { + type_set_init(s); + } else if (type_set__full(s)) { + type_set_grow(s); + } + GB_ASSERT(s->count < s->capacity); + GB_ASSERT(s->capacity >= 0); + + usize mask = s->capacity-1; + usize hash = cast(usize)pair.hash; + usize hash_index = (cast(usize)hash) & mask; + GB_ASSERT(hash_index < s->capacity); + for (usize i = 0; i < s->capacity; i++) { + TypeInfoPair *key = &s->keys[hash_index]; + GB_ASSERT(!are_types_identical_unique_tuples(key->type, pair.type)); + if (key->hash == TYPE_SET_TOMBSTONE || key->hash == 0) { + *key = pair; + s->count++; + return false; + } + hash_index = (hash_index+1)&mask; + } + + GB_PANIC("ptr set out of memory"); + return false; +} + +gb_internal bool type_set_update_with_mutex(TypeSet *s, Type *ptr, RWSpinLock *m) { // returns true if it previously existsed + TypeInfoPair pair = {ptr, type_hash_canonical_type(ptr)}; + return type_set_update_with_mutex(s, pair, m); +} + gb_internal Type *type_set_add(TypeSet *s, Type *ptr) { type_set_update(s, ptr); @@ -328,12 +373,20 @@ gb_internal u64 type_hash_canonical_type(Type *type) { if (type == nullptr) { return 0; } + u64 prev_hash = type->canonical_hash.load(std::memory_order_relaxed); + if (prev_hash != 0) { + return prev_hash; + } + u64 hash = fnv64a(nullptr, 0); TypeWriter w = {}; type_writer_make_hasher(&w, &hash); write_type_to_canonical_string(&w, type); + hash = hash ? hash : 1; + + type->canonical_hash.store(hash, std::memory_order_relaxed); - return hash ? hash : 1; + return hash; } gb_internal String type_to_canonical_string(gbAllocator allocator, Type *type) { diff --git a/src/name_canonicalization.hpp b/src/name_canonicalization.hpp index 304aff42e..00b450fbe 100644 --- a/src/name_canonicalization.hpp +++ b/src/name_canonicalization.hpp @@ -102,6 +102,8 @@ gb_internal Type *type_set_add (TypeSet *s, Type *ptr); gb_internal Type *type_set_add (TypeSet *s, TypeInfoPair pair); gb_internal bool type_set_update (TypeSet *s, Type *ptr); // returns true if it previously existed gb_internal bool type_set_update (TypeSet *s, TypeInfoPair pair); // returns true if it previously existed +gb_internal bool type_set_update_with_mutex(TypeSet *s, TypeInfoPair pair, RWSpinLock *m); +gb_internal bool type_set_update_with_mutex(TypeSet *s, Type *ptr, RWSpinLock *m); gb_internal bool type_set_exists (TypeSet *s, Type *ptr); gb_internal void type_set_remove (TypeSet *s, Type *ptr); gb_internal void type_set_clear (TypeSet *s); diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 5097e2bb6..06c1e4a58 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -134,6 +134,44 @@ gb_internal bool ptr_set_update(PtrSet *s, T ptr) { // returns true if it pre return false; } +template +gb_internal bool ptr_set_update_with_mutex(PtrSet *s, T ptr, RWSpinLock *m) { // returns true if it previously existsed + rwlock_acquire_upgrade(m); + if (ptr_set_exists(s, ptr)) { + rwlock_release_upgrade(m); + return true; + } + + rwlock_release_upgrade_and_acquire_write(m); + defer (rwlock_release_write(m)); + + if (s->keys == nullptr) { + ptr_set_init(s); + } else if (ptr_set__full(s)) { + ptr_set_grow(s); + } + GB_ASSERT(s->count < s->capacity); + GB_ASSERT(s->capacity >= 0); + + usize mask = s->capacity-1; + u32 hash = ptr_map_hash_key(ptr); + usize hash_index = (cast(usize)hash) & mask; + GB_ASSERT(hash_index < s->capacity); + for (usize i = 0; i < s->capacity; i++) { + T *key = &s->keys[hash_index]; + GB_ASSERT(*key != ptr); + if (*key == (T)PtrSet::TOMBSTONE || *key == 0) { + *key = ptr; + s->count++; + return false; + } + hash_index = (hash_index+1)&mask; + } + + GB_PANIC("ptr set out of memory"); + return false; +} + template gb_internal T ptr_set_add(PtrSet *s, T ptr) { ptr_set_update(s, ptr); diff --git a/src/threading.cpp b/src/threading.cpp index a0d1c4049..f1d9264e3 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -448,6 +448,44 @@ gb_internal void semaphore_wait(Semaphore *s) { } #endif +static const int RWLOCK_WRITER = 1; +static const int RWLOCK_UPGRADED = 2; +static const int RWLOCK_READER = 4; +struct RWSpinLock { + Futex bits; +}; + +void rwlock_release_write(RWSpinLock *l) { + l->bits.fetch_and(~(RWLOCK_WRITER | RWLOCK_UPGRADED), std::memory_order_release); + futex_signal(&l->bits); +} + +bool rwlock_try_acquire_upgrade(RWSpinLock *l) { + int value = l->bits.fetch_or(RWLOCK_UPGRADED, std::memory_order_acquire); + return (value & (RWLOCK_UPGRADED | RWLOCK_WRITER)) == 0; +} + +void rwlock_acquire_upgrade(RWSpinLock *l) { + while (!rwlock_try_acquire_upgrade(l)) { + futex_wait(&l->bits, RWLOCK_UPGRADED); + } +} +void rwlock_release_upgrade(RWSpinLock *l) { + l->bits.fetch_add(-RWLOCK_UPGRADED, std::memory_order_acq_rel); +} + +bool rwlock_try_release_upgrade_and_acquire_write(RWSpinLock *l) { + int expect = RWLOCK_UPGRADED; + return l->bits.compare_exchange_strong(expect, RWLOCK_WRITER, std::memory_order_acq_rel); +} + +void rwlock_release_upgrade_and_acquire_write(RWSpinLock *l) { + while (!rwlock_try_release_upgrade_and_acquire_write(l)) { + futex_wait(&l->bits, RWLOCK_WRITER); + } +} + + struct Parker { Futex state; }; diff --git a/src/types.cpp b/src/types.cpp index 6b94b1690..44f9394c7 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -334,6 +334,7 @@ struct Type { // NOTE(bill): These need to be at the end to not affect the unionized data std::atomic cached_size; std::atomic cached_align; + std::atomic canonical_hash; std::atomic flags; // TypeFlag bool failure; }; -- cgit v1.2.3