Begin interning ScopeMap strings

This commit is contained in:
gingerBill
2026-03-17 11:04:32 +00:00
parent d5a78a9cf1
commit 04cb889aed
18 changed files with 277 additions and 212 deletions

View File

@@ -2413,13 +2413,14 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
}
String name = arg->Ident.token.string;
auto interned = arg->Ident.interned;
operand->type = def.type;
operand->mode = def.mode;
operand->value = def.value;
Entity *found = scope_lookup_current(config_pkg->scope, name);
Entity *found = scope_lookup_current(config_pkg->scope, interned);
if (found != nullptr) {
if (found->kind != Entity_Constant) {
error(arg, "'#config' entity '%.*s' found but expected a constant", LIT(name));
@@ -2804,7 +2805,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
}
GB_ASSERT(type != nullptr);
String field_name = {};
InternedString field_name = {};
if (field_arg == nullptr) {
error(call, "Expected an identifier for field argument");
@@ -2812,9 +2813,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
}
if (field_arg->kind == Ast_Ident) {
field_name = field_arg->Ident.token.string;
field_name = field_arg->Ident.interned;
}
if (field_name.len == 0) {
if (field_name.value == 0) {
error(field_arg, "Expected an identifier for field argument");
return false;
}
@@ -2847,19 +2848,19 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
ERROR_BLOCK();
gbString type_str = type_to_string_shorthand(type);
error(ce->args[0],
"'%s' has no field named '%.*s'", type_str, LIT(field_name));
"'%s' has no field named '%s'", type_str, field_name.cstring());
gb_string_free(type_str);
Type *bt = base_type(type);
if (bt->kind == Type_Struct) {
check_did_you_mean_type(field_name, bt->Struct.fields);
check_did_you_mean_type(field_name.string(), bt->Struct.fields);
}
return false;
}
if (sel.indirect) {
gbString type_str = type_to_string_shorthand(type);
error(ce->args[0],
"Field '%.*s' is embedded via a pointer in '%s'", LIT(field_name), type_str);
"Field '%s' is embedded via a pointer in '%s'", field_name.cstring(), type_str);
gb_string_free(type_str);
return false;
}
@@ -2891,7 +2892,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
}
GB_ASSERT(type != nullptr);
String field_name = {};
InternedString field_name = {};
if (field_arg == nullptr) {
error(call, "Expected a constant (not-empty) string for field argument");
@@ -2901,9 +2902,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
Operand x = {};
check_expr(c, &x, field_arg);
if (x.mode == Addressing_Constant && x.value.kind == ExactValue_String) {
field_name = x.value.value_string;
field_name = string_interner_insert(x.value.value_string);
}
if (field_name.len == 0) {
if (field_name.value == 0) {
error(field_arg, "Expected a constant (non-empty) string for field argument");
return false;
}
@@ -2921,19 +2922,19 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
ERROR_BLOCK();
gbString type_str = type_to_string_shorthand(type);
error(ce->args[0],
"'%s' has no field named '%.*s'", type_str, LIT(field_name));
"'%s' has no field named '%s'", type_str, field_name.cstring());
gb_string_free(type_str);
Type *bt = base_type(type);
if (bt->kind == Type_Struct) {
check_did_you_mean_type(field_name, bt->Struct.fields);
check_did_you_mean_type(field_name.string(), bt->Struct.fields);
}
return false;
}
if (sel.indirect) {
gbString type_str = type_to_string_shorthand(type);
error(ce->args[0],
"Field '%.*s' is embedded via a pointer in '%s'", LIT(field_name), type_str);
"Field '%s' is embedded via a pointer in '%s'", field_name.string(), type_str);
gb_string_free(type_str);
return false;
}
@@ -4436,7 +4437,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
}
if (!fail && first_is_field_value) {
for_array(i, names) {
Selection sel = lookup_field(et, names[i], false);
Selection sel = lookup_field(et, string_interner_insert(names[i]), false);
if (sel.entity == nullptr) {
goto soa_zip_end;
}
@@ -6785,7 +6786,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
return false;
}
String field_name = x.value.value_string;
InternedString field_name = string_interner_insert(x.value.value_string);
Selection sel = lookup_field(type, field_name, false);
operand->mode = Addressing_Constant;
@@ -6865,12 +6866,12 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
return false;
}
String field_name = x.value.value_string;
InternedString field_name = string_interner_insert(x.value.value_string);
Selection sel = lookup_field(type, field_name, false);
if (sel.index.count == 0) {
gbString t = type_to_string(type);
error(ce->args[1], "'%.*s' is not a field of type %s", LIT(field_name), t);
error(ce->args[1], "'%s' is not a field of type %s", field_name.cstring(), t);
gb_string_free(t);
return false;
}
@@ -7625,25 +7626,25 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
return false;
}
String field_name = x.value.value_string;
InternedString field_name = string_interner_insert(x.value.value_string);
Selection sel = lookup_field(type, field_name, false);
if (sel.entity == nullptr) {
ERROR_BLOCK();
gbString type_str = type_to_string(bt);
error(ce->args[0],
"'%s' has no field named '%.*s'", type_str, LIT(field_name));
"'%s' has no field named '%s'", type_str, field_name.cstring());
gb_string_free(type_str);
if (bt->kind == Type_Struct) {
check_did_you_mean_type(field_name, bt->Struct.fields);
check_did_you_mean_type(field_name.string(), bt->Struct.fields);
}
return false;
}
if (sel.indirect) {
gbString type_str = type_to_string(bt);
error(ce->args[0],
"Field '%.*s' is embedded via a pointer in '%s'", LIT(field_name), type_str);
"Field '%s' is embedded via a pointer in '%s'", field_name.cstring(), type_str);
gb_string_free(type_str);
return false;
}

View File

@@ -156,9 +156,12 @@ gb_internal void override_entity_in_scope(Entity *original_entity, Entity *new_e
// NOTE(bill): The original_entity's scope may not be same scope that it was inserted into
// e.g. file entity inserted into its package scope
String original_name = original_entity->token.string;
auto original_intern = entity_interned_name(original_entity);
u32 hash = original_entity->interned_name_hash.load();
Scope *found_scope = nullptr;
Entity *found_entity = nullptr;
scope_lookup_parent(original_entity->scope, original_name, &found_scope, &found_entity);
scope_lookup_parent(original_entity->scope, original_intern, &found_scope, &found_entity, hash);
if (found_scope == nullptr) {
return;
}
@@ -170,9 +173,8 @@ gb_internal void override_entity_in_scope(Entity *original_entity, Entity *new_e
// Therefore two things can be done: the type can be assigned to state that it
// has been "evaluated" and the variant data can be copied across
u32 hash = string_hash(original_name);
rw_mutex_lock(&found_scope->mutex);
scope_map_insert(&found_scope->elements, original_name, hash, new_entity);
scope_map_insert(&found_scope->elements, original_intern, hash, new_entity);
rw_mutex_unlock(&found_scope->mutex);
original_entity->flags |= EntityFlag_Overridden;
@@ -993,7 +995,7 @@ gb_internal Entity *init_entity_foreign_library(CheckerContext *ctx, Entity *e)
error(ident, "foreign library names must be an identifier");
} else {
String name = ident->Ident.token.string;
Entity *found = scope_lookup(ctx->scope, name, ident->Ident.hash);
Entity *found = scope_lookup(ctx->scope, ident->Ident.interned, ident->Ident.hash);
if (found == nullptr) {
if (is_blank_ident(name)) {
@@ -1192,26 +1194,26 @@ gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeCon
if (!ac.objc_is_class_method) {
bool ok = true;
for (TypeNameObjCMetadataEntry const &entry : md->value_entries) {
if (entry.name == ac.objc_name) {
if (entry.interned.string() == ac.objc_name) {
error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
ok = false;
break;
}
}
if (ok) {
array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
array_add(&md->value_entries, TypeNameObjCMetadataEntry{string_interner_insert(ac.objc_name), e});
}
} else {
bool ok = true;
for (TypeNameObjCMetadataEntry const &entry : md->type_entries) {
if (entry.name == ac.objc_name) {
if (entry.interned.string() == ac.objc_name) {
error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
ok = false;
break;
}
}
if (ok) {
array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
array_add(&md->type_entries, TypeNameObjCMetadataEntry{string_interner_insert(ac.objc_name), e});
}
}
}

View File

@@ -183,11 +183,11 @@ gb_internal void populate_check_did_you_mean_objc_entity(StringSet *set, Entity
if (is_type) {
for (auto const &entry : objc_metadata->type_entries) {
string_set_add(set, entry.name);
string_set_add(set, entry.interned.string());
}
} else {
for (auto const &entry : objc_metadata->value_entries) {
string_set_add(set, entry.name);
string_set_add(set, entry.interned.string());
}
}
@@ -1329,7 +1329,7 @@ gb_internal bool polymorphic_assign_index(Type **gt_, i64 *dst_count, i64 source
Type *gt = *gt_;
GB_ASSERT(gt->kind == Type_Generic);
Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.name);
Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.interned_name);
GB_ASSERT(e != nullptr);
if (e->kind == Entity_TypeName) {
*gt_ = nullptr;
@@ -1430,7 +1430,7 @@ gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, T
if (poly->Array.generic_count != nullptr) {
Type *gt = poly->Array.generic_count;
GB_ASSERT(gt->kind == Type_Generic);
Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.name);
Entity *e = scope_lookup(gt->Generic.scope, gt->Generic.interned_name);
GB_ASSERT(e != nullptr);
if (e->kind == Entity_TypeName) {
Type *index = source->EnumeratedArray.index;
@@ -1770,9 +1770,9 @@ gb_internal Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *nam
GB_ASSERT(n->kind == Ast_Ident);
o->mode = Addressing_Invalid;
o->expr = n;
String name = n->Ident.token.string;
auto name = n->Ident.token.string;
Entity *e = scope_lookup(c->scope, name, n->Ident.hash);
Entity *e = scope_lookup(c->scope, n->Ident.interned);
if (e == nullptr) {
if (is_blank_ident(name)) {
error(n, "'_' cannot be used as a value");
@@ -5192,7 +5192,7 @@ gb_internal ExactValue get_constant_field_single(CheckerContext *c, ExactValue v
continue;
}
ast_node(fv, FieldValue, elem);
String name = fv->field->Ident.token.string;
auto name = fv->field->Ident.interned;
Selection sub_sel = lookup_field(node->tav.type, name, false);
if (sub_sel.index.count > 0 &&
sub_sel.index[0] == index) {
@@ -5459,7 +5459,7 @@ gb_internal Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *
}
} else */if (node->kind == Ast_Ident) {
String name = node->Ident.token.string;
return scope_lookup(c->scope, name, node->Ident.hash);
return scope_lookup(c->scope, node->Ident.interned);
} else if (!ident_only) if (node->kind == Ast_SelectorExpr) {
ast_node(se, SelectorExpr, node);
if (se->token.kind == Token_ArrowRight) {
@@ -5481,7 +5481,7 @@ gb_internal Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *
if (op_expr->kind == Ast_Ident) {
String op_name = op_expr->Ident.token.string;
Entity *e = scope_lookup(c->scope, op_name, op_expr->Ident.hash);
Entity *e = scope_lookup(c->scope,op_expr->Ident.interned);
if (e == nullptr) {
return nullptr;
}
@@ -5494,7 +5494,7 @@ gb_internal Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *
// If you can clean this up, please do but be really careful
String import_name = op_name;
Scope *import_scope = e->ImportName.scope;
String entity_name = selector->Ident.token.string;
auto entity_name = selector->Ident.interned;
check_op_expr = false;
entity = scope_lookup_current(import_scope, entity_name);
@@ -5520,7 +5520,7 @@ gb_internal Entity *check_entity_from_ident_or_selector(CheckerContext *c, Ast *
}
if (entity == nullptr && selector->kind == Ast_Ident) {
String field_name = selector->Ident.token.string;
auto field_name = selector->Ident.interned;
if (is_type_dynamic_array(type_deref(operand.type))) {
init_mem_allocator(c->checker);
}
@@ -5578,7 +5578,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
if (op_expr->kind == Ast_Ident) {
String op_name = op_expr->Ident.token.string;
Entity *e = scope_lookup(c->scope, op_name, op_expr->Ident.hash);
Entity *e = scope_lookup(c->scope, op_expr->Ident.interned);
add_entity_use(c, op_expr, e);
expr_entity = e;
@@ -5596,6 +5596,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
String import_name = op_name;
Scope *import_scope = e->ImportName.scope;
String entity_name = selector->Ident.token.string;
InternedString entity_name_interned = selector->Ident.interned;
if (import_scope == nullptr) {
ERROR_BLOCK();
@@ -5606,7 +5607,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
}
check_op_expr = false;
entity = scope_lookup_current(import_scope, entity_name);
entity = scope_lookup_current(import_scope, entity_name_interned);
bool allow_builtin = false;
if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) {
ERROR_BLOCK();
@@ -5654,7 +5655,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
}
if (entity == nullptr && selector->kind == Ast_Ident) {
String field_name = selector->Ident.token.string;
auto field_name = selector->Ident.interned;
Type *t = type_deref(operand->type);
if (t == nullptr) {
error(operand->expr, "Cannot use a selector expression on 0-value expression");
@@ -5993,15 +5994,14 @@ gb_internal bool is_type_valid_atomic_type(Type *elem) {
gb_internal bool check_identifier_exists(Scope *s, Ast *node, bool nested = false, Scope **out_scope = nullptr) {
switch (node->kind) {
case_ast_node(i, Ident, node);
String name = i->token.string;
if (nested) {
Entity *e = scope_lookup_current(s, name);
Entity *e = scope_lookup_current(s, i->interned, i->hash);
if (e != nullptr) {
if (out_scope) *out_scope = e->scope;
return true;
}
} else {
Entity *e = scope_lookup(s, name, i->hash);
Entity *e = scope_lookup(s, i->interned);
if (e != nullptr) {
if (out_scope) *out_scope = e->scope;
return true;
@@ -8972,7 +8972,7 @@ gb_internal bool attempt_implicit_selector_expr(CheckerContext *c, Operand *o, A
Type *enum_type = base_type(th);
GB_ASSERT(enum_type->kind == Type_Enum);
String name = ise->selector->Ident.token.string;
auto name = ise->selector->Ident.interned;
Entity *e = scope_lookup_current(enum_type->Enum.scope, name);
if (e == nullptr) {
@@ -9907,8 +9907,9 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slice<As
continue;
}
String name = ident->Ident.token.string;
auto interned = ident->Ident.interned;
Selection sel = lookup_field(type, name, o->mode == Addressing_Type);
Selection sel = lookup_field(type, interned, o->mode == Addressing_Type);
bool is_unknown = sel.entity == nullptr;
if (is_unknown) {
error(ident, "Unknown field '%.*s' in structure literal", LIT(name));
@@ -10863,8 +10864,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
continue;
}
String name = fv->field->Ident.token.string;
auto interned = fv->field->Ident.interned;
Selection sel = lookup_field(type, name, o->mode == Addressing_Type);
Selection sel = lookup_field(type, interned, o->mode == Addressing_Type);
if (sel.entity == nullptr) {
error(elem, "Unknown field '%.*s' in 'any' literal", LIT(name));
continue;

View File

@@ -484,7 +484,7 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O
}
if (ident_node != nullptr) {
ast_node(i, Ident, ident_node);
e = scope_lookup(ctx->scope, i->token.string, i->hash);
e = scope_lookup(ctx->scope, i->interned, i->hash);
if (e != nullptr && e->kind == Entity_Variable) {
used = (e->flags & EntityFlag_Used) != 0; // NOTE(bill): Make backup just in case
}
@@ -791,10 +791,10 @@ gb_internal bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us,
for (auto const &entry : scope->elements) {
Entity *decl = entry.value;
if (!is_entity_exported(decl, true)) continue;
String name = scope->elements.keys[entry.hash & (scope->elements.cap-1)];
u32 hash = entry.hash;
auto interned = scope->elements.keys[hash & (scope->elements.cap-1)];
Entity *found = scope_insert_with_name(ctx->scope, name, hash, decl);
Entity *found = scope_insert_with_name(ctx->scope, interned, hash, decl);
if (found != nullptr) {
gbString expr_str = expr_to_string(expr);
error(us->token,
@@ -1067,7 +1067,7 @@ gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod
Entity *found = nullptr;
if (!is_blank_ident(str)) {
found = scope_lookup_current(ctx->scope, str);
found = scope_lookup_current(ctx->scope, name->Ident.interned, name->Ident.hash);
}
if (found == nullptr) {
entity = alloc_entity_variable(ctx->scope, token, type, EntityState_Resolved);
@@ -1836,10 +1836,10 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
}
if (rs->vals.count == 1 && rs->vals[0] && rs->vals[0]->kind == Ast_Ident) {
AstIdent *ident = &rs->vals[0]->Ident;
String name = ident->token.string;
Entity *found = scope_lookup(ctx->scope, name, ident->hash);
Entity *found = scope_lookup(ctx->scope, ident->interned, ident->hash);
if (found && are_types_identical(found->type, t->BitSet.elem)) {
ERROR_BLOCK();
String name = ident->token.string;
gbString s = expr_to_string(expr);
error(rs->vals[0], "'%.*s' shadows a previous declaration which might be ambiguous with 'for (%.*s in %s)'", LIT(name), LIT(name), s);
error_line("\tSuggestion: Use a different identifier if iteration is wanted, or surround in parentheses if a normal for loop is wanted\n");
@@ -1888,10 +1888,10 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
}
if (rs->vals.count == 1 && rs->vals[0] && rs->vals[0]->kind == Ast_Ident) {
AstIdent *ident = &rs->vals[0]->Ident;
String name = ident->token.string;
Entity *found = scope_lookup(ctx->scope, name, ident->hash);
Entity *found = scope_lookup(ctx->scope, ident->interned, ident->hash);
if (found && are_types_identical(found->type, t->Map.key)) {
ERROR_BLOCK();
String name = ident->token.string;
gbString s = expr_to_string(expr);
error(rs->vals[0], "'%.*s' shadows a previous declaration which might be ambiguous with 'for (%.*s in %s)'", LIT(name), LIT(name), s);
error_line("\tSuggestion: Use a different identifier if iteration is wanted, or surround in parentheses if a normal for loop is wanted\n");
@@ -2032,7 +2032,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
Entity *found = nullptr;
if (!is_blank_ident(str)) {
found = scope_lookup_current(ctx->scope, str);
found = scope_lookup_current(ctx->scope, name->Ident.interned, name->Ident.hash);
}
if (found == nullptr) {
entity = alloc_entity_variable(ctx->scope, token, type, EntityState_Resolved);
@@ -2126,7 +2126,7 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f
Entity *found = nullptr;
// NOTE(bill): Ignore assignments to '_'
if (!is_blank_ident(str)) {
found = scope_lookup_current(ctx->scope, str);
found = scope_lookup_current(ctx->scope, name->Ident.interned, name->Ident.hash);
new_name_count += 1;
}
if (found == nullptr) {

View File

@@ -5,7 +5,9 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
gb_internal void populate_using_array_index(CheckerContext *ctx, Ast *node, AstField *field, Type *t, String name, i32 idx) {
t = base_type(t);
GB_ASSERT(t->kind == Type_Array);
Entity *e = scope_lookup_current(ctx->scope, name);
InternedString interned = string_interner_insert(name);
Entity *e = scope_lookup_current(ctx->scope, interned);
if (e != nullptr) {
gbString str = nullptr;
defer (gb_string_free(str));
@@ -47,7 +49,8 @@ gb_internal void populate_using_entity_scope(CheckerContext *ctx, Ast *node, Ast
for (Entity *f : t->Struct.fields) {
GB_ASSERT(f->kind == Entity_Variable);
String name = f->token.string;
Entity *e = scope_lookup_current(ctx->scope, name);
InternedString interned = entity_interned_name(f);
Entity *e = scope_lookup_current(ctx->scope, interned);
if (e != nullptr && name != "_") {
gbString ot = type_to_string(original_type);
// TODO(bill): Better type error
@@ -423,7 +426,7 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly
Ast *s = type_expr->TypeidType.specialization;
specialization = check_type(ctx, s);
}
type = alloc_type_generic(ctx->scope, 0, str_lit(""), specialization);
type = alloc_type_generic(ctx->scope, 0, string_interner_insert(str_lit("")), specialization);
} else {
type = check_type(ctx, type_expr);
if (is_type_polymorphic(type)) {
@@ -981,7 +984,9 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam
e->Constant.docs = docs;
e->Constant.comment = comment;
if (scope_lookup_current(ctx->scope, name) != nullptr) {
auto interned = entity_interned_name(e);
if (scope_lookup_current(ctx->scope, interned) != nullptr) {
error(ident, "'%.*s' is already declared in this enumeration", LIT(name));
} else {
add_entity(ctx, ctx->scope, nullptr, e);
@@ -1043,6 +1048,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type,
CommentGroup *comment = f->comment;
String name = f->name->Ident.token.string;
InternedString interned = f->name->Ident.interned;
if (f->type == nullptr) {
error(field, "A bit_field's field must have a type");
@@ -1093,7 +1099,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type,
gb_string_free(s);
}
if (scope_lookup_current(ctx->scope, name) != nullptr) {
if (scope_lookup_current(ctx->scope, interned) != nullptr) {
error(f->name, "'%.*s' is already declared in this bit_field", LIT(name));
} else {
i64 bit_size_i64 = exact_value_to_i64(bit_size);
@@ -1513,7 +1519,7 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special
// NOTE(bill, 2018-12-14): This is needed to override polymorphic named constants in types
if (st->kind == Type_Generic && t_e->kind == Entity_Constant) {
Entity *e = scope_lookup(st->Generic.scope, st->Generic.name);
Entity *e = scope_lookup(st->Generic.scope, st->Generic.interned_name);
GB_ASSERT(e != nullptr);
if (modify_type) {
e->kind = Entity_Constant;
@@ -1566,7 +1572,7 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special
// NOTE(bill, 2018-12-14): This is needed to override polymorphic named constants in types
if (st->kind == Type_Generic && t_e->kind == Entity_Constant) {
Entity *e = scope_lookup(st->Generic.scope, st->Generic.name);
Entity *e = scope_lookup(st->Generic.scope, st->Generic.interned_name);
GB_ASSERT(e != nullptr);
if (modify_type) {
e->kind = Entity_Constant;
@@ -1905,7 +1911,7 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
detemine_type_from_operand = true;
type = t_invalid;
} else {
type = alloc_type_generic(ctx->scope, 0, str_lit(""), specialization);
type = alloc_type_generic(ctx->scope, 0, string_interner_insert(str_lit("")), specialization);
}
} else {
type = t_typeid;
@@ -2330,8 +2336,7 @@ gb_internal bool ast_references_poly_params(Scope *scope, Ast *node) {
}
switch (node->kind) {
case Ast_Ident: {
String name = node->Ident.token.string;
Entity *e = scope_lookup(scope, name);
Entity *e = scope_lookup(scope, node->Ident.interned, node->Ident.hash);
if (e != nullptr && e->kind == Entity_TypeName && e->type != nullptr && e->type->kind == Type_Generic) {
return true;
}
@@ -2408,7 +2413,7 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res
param_value = handle_parameter_value(ctx, nullptr, &type, default_value, false);
} else {
if (ctx->allow_polymorphic_types && ast_references_poly_params(ctx->scope, field->type)) {
type = alloc_type_generic(ctx->scope, 0, str_lit("$deferred_return"), nullptr);
type = alloc_type_generic(ctx->scope, 0, string_interner_insert(str_lit("$deferred_return")), nullptr);
} else {
type = check_type(ctx, field->type);
}
@@ -3534,7 +3539,7 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
Ast *s = pt->specialization;
specific = check_type(&c, s);
}
Type *t = alloc_type_generic(ctx->scope, 0, token.string, specific);
Type *t = alloc_type_generic(ctx->scope, 0, ident->Ident.interned, specific);
if (ctx->allow_polymorphic_types) {
if (ctx->disallow_polymorphic_return_types) {
error(ident, "Undeclared polymorphic parameter '%.*s' in return type", LIT(token.string));

View File

@@ -372,10 +372,10 @@ gb_internal void check_close_scope(CheckerContext *c) {
}
gb_internal Entity *scope_lookup_current(Scope *s, String const &name, u32 hash) {
gb_internal Entity *scope_lookup_current(Scope *s, InternedString name, u32 hash) {
// Entity **found = string_map_get(&s->elements, name);
if (hash == 0) {
hash = string_hash(name);
hash = name.hash();
}
Entity *found = scope_map_get(&s->elements, name, hash);
if (found) {
@@ -387,13 +387,13 @@ gb_internal Entity *scope_lookup_current(Scope *s, String const &name, u32 hash)
gb_global std::atomic<bool> in_single_threaded_checker_stage;
gb_internal void scope_lookup_parent(Scope *scope, String const &name, Scope **scope_, Entity **entity_, u32 hash) {
gb_internal void scope_lookup_parent(Scope *scope, InternedString name, Scope **scope_, Entity **entity_, u32 hash) {
bool is_single_threaded = in_single_threaded_checker_stage.load(std::memory_order_relaxed);
if (scope != nullptr) {
bool gone_thru_proc = false;
bool gone_thru_package = false;
if (!hash) {
hash = string_hash(name);
hash = name.hash();
}
for (Scope *s = scope; s != nullptr; s = s->parent) {
Entity *found = nullptr;
@@ -434,14 +434,14 @@ gb_internal void scope_lookup_parent(Scope *scope, String const &name, Scope **s
if (scope_) *scope_ = nullptr;
}
gb_internal Entity *scope_lookup(Scope *s, String const &name, u32 hash) {
gb_internal Entity *scope_lookup(Scope *s, InternedString interned, u32 hash) {
Entity *entity = nullptr;
scope_lookup_parent(s, name, nullptr, &entity, hash);
scope_lookup_parent(s, interned, nullptr, &entity, hash);
return entity;
}
gb_internal Entity *scope_insert_with_name_no_mutex(Scope *s, String const &name, u32 hash, Entity *entity) {
if (name == "") {
gb_internal Entity *scope_insert_with_name_no_mutex(Scope *s, InternedString name, u32 hash, Entity *entity) {
if (name.value == 0) {
return nullptr;
}
Entity *found = nullptr;
@@ -476,8 +476,8 @@ end:;
}
gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, u32 hash, Entity *entity) {
if (name == "") {
gb_internal Entity *scope_insert_with_name(Scope *s, InternedString name, u32 hash, Entity *entity) {
if (name.value == 0) {
return nullptr;
}
Entity *found = nullptr;
@@ -519,15 +519,9 @@ end:;
}
gb_internal Entity *scope_insert(Scope *s, Entity *entity) {
String name = entity->token.string;
u32 hash = 0;
Ast *ident = entity->identifier.load(std::memory_order_relaxed);
if (ident != nullptr) {
hash = ident->Ident.hash;
}
if (hash == 0) {
hash = string_hash(name);
}
auto name = entity_interned_name(entity);
u32 hash = entity->interned_name_hash.load(std::memory_order_relaxed);
GB_ASSERT(hash != 0);
if (in_single_threaded_checker_stage.load(std::memory_order_relaxed)) {
return scope_insert_with_name_no_mutex(s, name, hash, entity);
} else {
@@ -536,15 +530,9 @@ gb_internal Entity *scope_insert(Scope *s, Entity *entity) {
}
gb_internal Entity *scope_insert_no_mutex(Scope *s, Entity *entity) {
String name = entity->token.string;
u32 hash = 0;
Ast *ident = entity->identifier.load(std::memory_order_relaxed);
if (ident != nullptr) {
hash = ident->Ident.hash;
}
if (hash == 0) {
hash = string_hash(name);
}
auto name = string_interner_insert(entity->token.string);
u32 hash = entity->interned_name_hash.load(std::memory_order_relaxed);
GB_ASSERT(hash != 0);
return scope_insert_with_name_no_mutex(s, name, hash, entity);
}
@@ -679,7 +667,7 @@ gb_internal bool check_vet_shadowing(Checker *c, Entity *e, VettedEntity *ve) {
return false;
}
Entity *shadowed = scope_lookup(parent, name);
Entity *shadowed = scope_lookup(parent, entity_interned_name(e));
if (shadowed == nullptr) {
return false;
}
@@ -961,8 +949,9 @@ gb_internal AstPackage *try_get_core_package(CheckerInfo *info, String 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);
InternedString key = string_interner_insert(n);
AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name));
Entity *e = scope_lookup(p->scope, n);
Entity *e = scope_lookup(p->scope, key);
GB_ASSERT_MSG(e != nullptr, "%s", name);
GB_ASSERT(c->decl != nullptr);
e->flags |= EntityFlag_Used;
@@ -974,8 +963,9 @@ gb_internal void add_package_dependency(CheckerContext *c, char const *package_n
gb_internal void try_to_add_package_dependency(CheckerContext *c, char const *package_name, char const *name) {
String n = make_string_c(name);
InternedString key = string_interner_insert(n);
AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name));
Entity *e = scope_lookup(p->scope, n);
Entity *e = scope_lookup(p->scope, key);
if (e == nullptr) {
return;
}
@@ -1373,6 +1363,9 @@ gb_internal void init_universal(void) {
BuiltinProcId id = cast(BuiltinProcId)i;
String name = builtin_procs[i].name;
if (name != "") {
u32 hash = 0;
InternedString interned = string_interner_insert(name, 0, &hash);
Entity *entity = alloc_entity(Entity_Builtin, nullptr, make_token_ident(name), t_invalid);
entity->Builtin.id = id;
switch (builtin_procs[i].pkg) {
@@ -1381,7 +1374,7 @@ gb_internal void init_universal(void) {
break;
case BuiltinProcPkg_intrinsics:
add_global_entity(entity, intrinsics_pkg->scope);
GB_ASSERT(scope_lookup_current(intrinsics_pkg->scope, name) != nullptr);
GB_ASSERT(scope_lookup_current(intrinsics_pkg->scope, interned, hash) != nullptr);
break;
}
}
@@ -2763,7 +2756,7 @@ gb_internal void add_dependency_to_set_threaded(Checker *c, Entity *entity) {
gb_internal void force_add_dependency_entity(Checker *c, Scope *scope, String const &name) {
Entity *e = scope_lookup(scope, name);
Entity *e = scope_lookup(scope, string_interner_insert(name));
if (e == nullptr) {
return;
}
@@ -2775,7 +2768,9 @@ gb_internal void force_add_dependency_entity(Checker *c, Scope *scope, String co
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"));
u32 hash = 0;
InternedString interned = string_interner_insert(str_lit("Test_Signature"), 0, &hash);
Entity *test_signature = scope_lookup_current(testing_scope, interned, hash);
Scope *s = pkg->scope;
for (auto const &entry : s->elements) {
@@ -3229,7 +3224,9 @@ gb_internal void check_single_global_entity(Checker *c, Entity *e, DeclInfo *d);
gb_internal Entity *find_core_entity(Checker *c, String name) {
Entity *e = scope_lookup_current(c->info.runtime_package->scope, name);
u32 hash = 0;
InternedString interned = string_interner_insert(name, 0, &hash);
Entity *e = scope_lookup_current(c->info.runtime_package->scope, interned, hash);
if (e == nullptr) {
compiler_error("Could not find type declaration for '%.*s'\n"
, LIT(name));
@@ -3239,7 +3236,9 @@ gb_internal Entity *find_core_entity(Checker *c, String name) {
}
gb_internal Type *find_core_type(Checker *c, String name) {
Entity *e = scope_lookup_current(c->info.runtime_package->scope, name);
u32 hash = 0;
InternedString interned = string_interner_insert(name, 0, &hash);
Entity *e = scope_lookup_current(c->info.runtime_package->scope, interned, hash);
if (e == nullptr) {
compiler_error("Could not find type declaration for '%.*s'\n"
, LIT(name));
@@ -3254,8 +3253,10 @@ gb_internal Type *find_core_type(Checker *c, String name) {
gb_internal Entity *find_entity_in_pkg(CheckerInfo *info, String const &pkg, String const &name) {
u32 hash = 0;
InternedString interned = string_interner_insert(name, 0, &hash);
AstPackage *package = get_core_package(info, pkg);
Entity *e = scope_lookup_current(package->scope, name);
Entity *e = scope_lookup_current(package->scope, interned, hash);
if (e == nullptr) {
compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg), LIT(name));
// NOTE(bill): This will exit the program as it's cannot continue without it!
@@ -3264,8 +3265,10 @@ gb_internal Entity *find_entity_in_pkg(CheckerInfo *info, String const &pkg, Str
}
gb_internal Type *find_type_in_pkg(CheckerInfo *info, String const &pkg, String const &name) {
u32 hash = 0;
InternedString interned = string_interner_insert(name, 0, &hash);
AstPackage *package = get_core_package(info, pkg);
Entity *e = scope_lookup_current(package->scope, name);
Entity *e = scope_lookup_current(package->scope, interned, hash);
if (e == nullptr) {
compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg), LIT(name));
// NOTE(bill): This will exit the program as it's cannot continue without it!
@@ -4558,7 +4561,9 @@ gb_internal void check_builtin_attributes(CheckerContext *ctx, Entity *e, Array<
if (name == "builtin") {
mutex_lock(&ctx->info->builtin_mutex);
add_entity(ctx, builtin_pkg->scope, nullptr, e);
GB_ASSERT(scope_lookup(builtin_pkg->scope, e->token.string) != nullptr);
auto interned = entity_interned_name(e);
u32 hash = e->interned_name_hash.load();
GB_ASSERT(scope_lookup(builtin_pkg->scope, interned, hash) != nullptr);
if (value != nullptr) {
error(value, "'builtin' cannot have a field value");
}
@@ -7514,7 +7519,7 @@ gb_internal void check_parsed_files(Checker *c) {
Scope *s = c->info.init_scope;
GB_ASSERT(s != nullptr);
GB_ASSERT(s->flags&ScopeFlag_Init);
Entity *e = scope_lookup_current(s, str_lit("main"));
Entity *e = scope_lookup_current(s, string_interner_insert(str_lit("main")));
if (e == nullptr) {
Token token = {};
token.pos.file_id = 0;

View File

@@ -278,12 +278,12 @@ struct ScopeMapSlot {
enum { SCOPE_MAP_INLINE_CAP = 16 };
struct ScopeMap {
String inline_keys [SCOPE_MAP_INLINE_CAP];
ScopeMapSlot inline_slots[SCOPE_MAP_INLINE_CAP];
String * keys;
ScopeMapSlot *slots;
u32 count;
u32 cap;
InternedString inline_keys [SCOPE_MAP_INLINE_CAP];
ScopeMapSlot inline_slots[SCOPE_MAP_INLINE_CAP];
InternedString *keys;
ScopeMapSlot * slots;
u32 count;
u32 cap;
};
gb_internal gb_inline u32 scope_map_max_load(u32 cap) {
@@ -298,8 +298,8 @@ gb_internal gb_inline void scope_map_init(ScopeMap *m) {
gb_internal Entity *scope_map_insert_for_rehash(
String *keys, ScopeMapSlot *slots, u32 mask,
String key, u32 hash, Entity *value) {
InternedString *keys, ScopeMapSlot *slots, u32 mask,
InternedString key, u32 hash, Entity *value) {
u32 pos = hash & mask;
u32 dist = 0;
@@ -316,7 +316,7 @@ gb_internal Entity *scope_map_insert_for_rehash(
u32 existing_dist = (pos - s->hash) & mask;
if (dist > existing_dist) {
String tmp_key = keys[pos];
auto tmp_key = keys[pos];
u32 tmp_hash = s->hash;
Entity *tmp_value = s->value;
@@ -335,12 +335,12 @@ gb_internal Entity *scope_map_insert_for_rehash(
}
}
gb_internal gb_inline void scope_map_allocate_entries(u32 cap, String **keys, ScopeMapSlot **slots) {
gb_internal gb_inline void scope_map_allocate_entries(u32 cap, InternedString **keys, ScopeMapSlot **slots) {
Arena *arena = get_arena(ThreadArena_Permanent);
isize size = (gb_size_of(String) + gb_size_of(ScopeMapSlot)) * cap;
isize size = (gb_size_of(InternedString) + gb_size_of(ScopeMapSlot)) * cap;
u8 *data = cast(u8 *)arena_alloc(arena, size, 8);
*keys = cast(String *)data;
*keys = cast(InternedString *)data;
*slots = cast(ScopeMapSlot *)(*keys + cap);
// *keys = permanent_alloc_array<String>(cap);
@@ -352,8 +352,8 @@ gb_internal void scope_map_grow(ScopeMap *m) {
u32 new_cap = m->cap << 1;
u32 new_mask = new_cap - 1;
String * new_keys;
ScopeMapSlot *new_slots;
InternedString *new_keys;
ScopeMapSlot * new_slots;
scope_map_allocate_entries(new_cap, &new_keys, &new_slots);
if (m->count > 0) {
@@ -383,7 +383,7 @@ gb_internal void scope_map_reserve(ScopeMap *m, isize capacity) {
gb_internal Entity *scope_map_insert(ScopeMap *m, String key, u32 hash, Entity *value) {
gb_internal Entity *scope_map_insert(ScopeMap *m, InternedString key, u32 hash, Entity *value) {
if (m->slots == nullptr) {
scope_map_init(m);
}
@@ -415,7 +415,7 @@ gb_internal Entity *scope_map_insert(ScopeMap *m, String key, u32 hash, Entity *
u32 existing_dist = (pos - s->hash) & mask;
if (dist > existing_dist) {
String tmp_key = m->keys[pos];
auto tmp_key = m->keys[pos];
u32 tmp_hash = s->hash;
Entity *tmp_value = s->value;
@@ -434,7 +434,7 @@ gb_internal Entity *scope_map_insert(ScopeMap *m, String key, u32 hash, Entity *
}
}
gb_internal Entity *scope_map_get(ScopeMap *m, String key, u32 hash) {
gb_internal Entity *scope_map_get(ScopeMap *m, InternedString key, u32 hash) {
u32 mask = m->cap-1;
u32 pos = hash & mask;
u32 dist = 0;
@@ -883,8 +883,8 @@ gb_internal Entity *entity_of_node(Ast *expr);
// gb_internal Entity *scope_lookup_current(Scope *s, String const &name, u32 hash=0);
gb_internal Entity *scope_lookup (Scope *s, String const &name, u32 hash=0);
gb_internal void scope_lookup_parent (Scope *s, String const &name, Scope **scope_, Entity **entity_, u32 hash=0);
gb_internal Entity *scope_lookup (Scope *s, InternedString interned, u32 hash=0);
gb_internal void scope_lookup_parent (Scope *s, InternedString name, Scope **scope_, Entity **entity_, u32 hash=0);
gb_internal Entity *scope_insert (Scope *s, Entity *entity);

View File

@@ -1050,7 +1050,8 @@ gb_internal OdinDocArray<OdinDocScopeEntry> odin_doc_add_pkg_entries(OdinDocWrit
defer (array_free(&entries));
for (auto const &element : pkg->scope->elements) {
String name = pkg->scope->elements.keys[element.hash & (pkg->scope->elements.cap-1)];
u32 hash = element.hash;
auto interned = pkg->scope->elements.keys[hash & (pkg->scope->elements.cap-1)];
Entity *e = element.value;
switch (e->kind) {
case Entity_Invalid:
@@ -1079,7 +1080,7 @@ gb_internal OdinDocArray<OdinDocScopeEntry> odin_doc_add_pkg_entries(OdinDocWrit
}
OdinDocScopeEntry entry = {};
entry.name = odin_doc_write_string(w, name);
entry.name = odin_doc_write_string(w, interned.string());
entry.entity = odin_doc_add_entity(w, e);
array_add(&entries, entry);
}

View File

@@ -141,7 +141,7 @@ enum ProcedureOptimizationMode : u8 {
BlockingMutex global_type_name_objc_metadata_mutex;
struct TypeNameObjCMetadataEntry {
String name;
InternedString interned;
Entity *entity;
};
struct TypeNameObjCMetadata {
@@ -169,6 +169,10 @@ struct Entity {
Scope * scope;
Type * type;
std::atomic<Ast *> identifier; // Can be nullptr
std::atomic<InternedString> interned_name;
std::atomic<u32> interned_name_hash;
DeclInfo * decl_info;
std::atomic<DeclInfo *> parent_proc_decl; // nullptr if in file/global scope
AstFile * file;
@@ -300,6 +304,16 @@ struct Entity {
};
};
gb_internal InternedString entity_interned_name(Entity *entity) {
auto name = entity->interned_name.load();
if (name.value == 0) {
name = string_interner_insert(entity->token.string);
entity->interned_name.store(name);
entity->interned_name_hash.store(name.hash());
}
return name;
}
gb_internal bool is_entity_kind_exported(EntityKind kind, bool allow_builtin = false) {
switch (kind) {
case Entity_Builtin:
@@ -345,16 +359,17 @@ gb_internal bool entity_has_deferred_procedure(Entity *e) {
gb_global std::atomic<u64> global_entity_id;
// NOTE(bill): This exists to allow for bulk allocations of entities all at once to improve performance for type generation
#define INTERNAL_ENTITY_INIT(entity, kind_, scope_, token_, type_) do { \
(entity)->kind = (kind_); \
(entity)->state = EntityState_Unresolved; \
(entity)->scope = (scope_); \
(entity)->token = (token_); \
(entity)->type = (type_); \
(entity)->id = 1 + global_entity_id.fetch_add(1); \
if ((token_).pos.file_id) { \
entity->file = thread_unsafe_get_ast_file_from_id((token_).pos.file_id); \
} \
#define INTERNAL_ENTITY_INIT(e_, kind_, scope_, token_, type_) do { \
(e_)->kind = (kind_); \
(e_)->state = EntityState_Unresolved; \
(e_)->scope = (scope_); \
(e_)->token = (token_); \
(e_)->type = (type_); \
(e_)->id = 1 + global_entity_id.fetch_add(1); \
if ((token_).pos.file_id) { \
e_->file = thread_unsafe_get_ast_file_from_id((token_).pos.file_id); \
} \
entity_interned_name(e_); \
} while (0)

View File

@@ -2946,7 +2946,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
AstPackage *pkg = get_runtime_package(m->info);
String name = str_lit("exit");
Entity *e = scope_lookup_current(pkg->scope, name);
Entity *e = scope_lookup_current(pkg->scope, string_interner_insert(name));
if (e == nullptr) {
compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg->name), LIT(name));
}

View File

@@ -1819,11 +1819,12 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
for (isize i = 0; i < elem_count; i++) {
ast_node(fv, FieldValue, cl->elems[i]);
String name = fv->field->Ident.token.string;
InternedString interned = fv->field->Ident.interned;
TypeAndValue tav = fv->value->tav;
GB_ASSERT(tav.mode != Addressing_Invalid);
Selection sel = lookup_field(type, name, false);
Selection sel = lookup_field(type, interned, false);
GB_ASSERT(!sel.indirect);
Entity *f = type->Struct.fields[sel.index[0]];

View File

@@ -4362,9 +4362,9 @@ gb_internal lbAddr lb_get_soa_variable_addr(lbProcedure *p, Entity *e) {
}
gb_internal lbValue lb_get_using_variable(lbProcedure *p, Entity *e) {
GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using);
String name = e->token.string;
InternedString interned = entity_interned_name(e);
Entity *parent = e->using_parent;
Selection sel = lookup_field(parent->type, name, false);
Selection sel = lookup_field(parent->type, interned, false);
GB_ASSERT(sel.entity != nullptr);
lbValue *pv = map_get(&p->module->values, parent);
@@ -4379,7 +4379,7 @@ gb_internal lbValue lb_get_using_variable(lbProcedure *p, Entity *e) {
} else if (pv != nullptr) {
v = *pv;
} else {
GB_ASSERT_MSG(e->using_expr != nullptr, "%.*s", LIT(name));
GB_ASSERT_MSG(e->using_expr != nullptr, "%.*s", LIT(e->token.string));
v = lb_build_addr_ptr(p, e->using_expr);
}
GB_ASSERT(v.value != nullptr);
@@ -5362,8 +5362,8 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
for (Ast *elem : cl->elems) {
ast_node(fv, FieldValue, elem);
String name = fv->field->Ident.token.string;
Selection sel = lookup_field(bt, name, false);
InternedString interned = fv->field->Ident.interned;
Selection sel = lookup_field(bt, interned, false);
GB_ASSERT(sel.is_bit_field);
GB_ASSERT(!sel.indirect);
GB_ASSERT(sel.index.count == 1);
@@ -5556,8 +5556,8 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (elem->kind == Ast_FieldValue) {
ast_node(fv, FieldValue, elem);
String name = fv->field->Ident.token.string;
Selection sel = lookup_field(bt, name, false);
InternedString interned = fv->field->Ident.interned;
Selection sel = lookup_field(bt, interned, false);
GB_ASSERT(!sel.indirect);
elem = fv->value;
@@ -5811,12 +5811,12 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (elem->kind == Ast_FieldValue) {
ast_node(fv, FieldValue, elem);
Selection sel = lookup_field(bt, fv->field->Ident.token.string, false);
Selection sel = lookup_field(bt, fv->field->Ident.interned, false);
index = sel.index[0];
elem = fv->value;
} else {
TypeAndValue tav = type_and_value_of_expr(elem);
Selection sel = lookup_field(bt, field_names[field_index], false);
Selection sel = lookup_field(bt, string_interner_insert(field_names[field_index]), false);
index = sel.index[0];
}
@@ -5958,7 +5958,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
case_ast_node(se, SelectorExpr, expr);
Ast *sel_node = unparen_expr(se->selector);
if (sel_node->kind == Ast_Ident) {
String selector = sel_node->Ident.token.string;
InternedString selector = sel_node->Ident.interned;
TypeAndValue tav = type_and_value_of_expr(se->expr);
if (tav.mode == Addressing_Invalid) {
@@ -5978,7 +5978,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
GB_ASSERT(e->kind == Entity_Procedure);
return lb_addr(lb_find_value_from_entity(p->module, e));
}
GB_PANIC("Unreachable %.*s", LIT(selector));
GB_PANIC("Unreachable %s", selector.cstring());
}
if (se->swizzle_count > 0) {

View File

@@ -3406,7 +3406,7 @@ gb_internal lbAddr lb_add_global_generated_from_procedure(lbProcedure *p, Type *
gb_internal lbValue lb_find_runtime_value(lbModule *m, String const &name) {
AstPackage *p = m->info->runtime_package;
Entity *e = scope_lookup_current(p->scope, name);
Entity *e = scope_lookup_current(p->scope, string_interner_insert(name));
return lb_find_value_from_entity(m, e);
}
gb_internal lbValue lb_find_package_value(lbModule *m, String const &pkg, String const &name) {

View File

@@ -1012,7 +1012,7 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue
gb_internal lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name) {
AstPackage *pkg = m->info->runtime_package;
Entity *e = scope_lookup_current(pkg->scope, name);
Entity *e = scope_lookup_current(pkg->scope, string_interner_insert(name));
GB_ASSERT_MSG(e != nullptr, "Runtime procedure not found: %s", name);
return lb_find_procedure_value_from_entity(m, e);
}

View File

@@ -3588,7 +3588,7 @@ int main(int arg_count, char const **arg_ptr) {
MAIN_TIME_SECTION("initialization");
g_string_interner = string_interner_create();
init_string_interner();
init_global_error_collector();
init_keyword_hash_table();
init_terminal();

View File

@@ -559,6 +559,8 @@ gb_internal void write_canonical_parent_prefix(TypeWriter *w, Entity *e) {
// no prefix
return;
}
InternedString interned = entity_interned_name(e);
if (e->parent_proc_decl.load(std::memory_order_relaxed)) {
Entity *p = e->parent_proc_decl.load(std::memory_order_relaxed)->entity;
write_canonical_parent_prefix(w, p);
@@ -569,7 +571,7 @@ gb_internal void write_canonical_parent_prefix(TypeWriter *w, Entity *e) {
}
type_writer_appendc(w, CANONICAL_NAME_SEPARATOR);
} else if (e->pkg && (scope_lookup_current(e->pkg->scope, e->token.string) == e)) {
} else if (e->pkg && (scope_lookup_current(e->pkg->scope, interned) == e)) {
type_writer_append(w, e->pkg->name.text, e->pkg->name.len);
if (e->pkg->name == "llvm") {
type_writer_appendc(w, "$");

View File

@@ -10,8 +10,11 @@ struct InternedString {
return this->value == other.value;
}
String load() const;
char const *load_cstring() const;
String string() const;
char const *cstring() const;
u32 hash() const;
bool is_blank() const;
};
struct alignas(STRING_INTERN_CACHE_LINE) StringInternCell {
std::atomic<u64> hashes [STRING_INTERNER_CELL_WIDTH];
@@ -38,10 +41,11 @@ struct StringInterner {
};
gb_internal StringInterner *string_interner_create();
gb_internal InternedString string_interner_insert(String str, u32 hash=0);
gb_internal InternedString string_interner_insert(String str, u32 hash=0, u32 *new_hash_=nullptr);
gb_internal String string_interner_load(InternedString interned);
gb_global StringInterner *g_string_interner;
gb_global InternedString g_interned_blank_ident;
struct StringInternerThreadLocalArena {
u8 *data;
@@ -52,7 +56,7 @@ gb_thread_local gb_global StringInternerThreadLocalArena g_interner_arena;
gb_internal void string_interner_thread_local_arena_init(StringInternerThreadLocalArena *tl_arena);
gb_internal void *string_interner_thread_local_arena_alloc(StringInternerThreadLocalArena *tl_arena, isize size, isize alignment);
gb_internal StringInterner *string_interner_create() {
gb_internal void init_string_interner() {
StaticArena arena = {};
static_arena_init(&arena, 1<<30, STATIC_ARENA_DEFAULT_COMMIT_BLOCK_SIZE);
@@ -63,7 +67,10 @@ gb_internal StringInterner *string_interner_create() {
interner->cell_mask = cell_mask;
interner->cells = cast(StringInternCell *)static_arena_alloc(&interner->arena, cell_size * gb_size_of(StringInternCell), STRING_INTERN_CACHE_LINE);
interner->track_count = false;
return interner;
g_string_interner = interner;
g_interned_blank_ident = string_interner_insert(str_lit("_"));
}
gb_internal String string_interner_load(InternedString interned) {
@@ -89,22 +96,31 @@ gb_internal char const *string_interner_load_cstring(InternedString interned) {
return cast(char const *)text;
}
String InternedString::load() const {
String InternedString::string() const {
return string_interner_load(*this);
}
char const *InternedString::load_cstring() const {
char const *InternedString::cstring() const {
return string_interner_load_cstring(*this);
}
u32 InternedString::hash() const {
String s = string_interner_load(*this);
return string_hash(s);
}
bool InternedString::is_blank() const {
return this->value == g_interned_blank_ident.value;
}
gb_internal InternedString string_interner_insert(String str, u32 hash) {
gb_internal InternedString string_interner_insert(String str, u32 hash, u32 *new_hash_) {
StringInterner* interner = g_string_interner;
if (str.len == 0) {
if (new_hash_) *new_hash_ = string_hash(String{});
return {};
}
if (hash == 0) {
hash = string_hash(str);
}
if (new_hash_) *new_hash_ = hash;
u64 cell_idx = hash & interner->cell_mask;
StringInternCell *cell = &interner->cells[cell_idx];
@@ -175,14 +191,14 @@ gb_internal InternedString string_interner_insert(String str, u32 hash) {
return offset;
}
gb_internal char const *string_intern_cstring(String str) {
InternedString i = string_interner_insert(str, 0);
gb_internal char const *string_intern_cstring(String str, u32 *hash_=nullptr) {
InternedString i = string_interner_insert(str, 0, hash_);
return string_interner_load_cstring(i);
}
gb_internal String string_intern_string(String str) {
InternedString i = string_interner_insert(str, 0);
gb_internal String string_intern_string(String str, u32 *hash_=nullptr) {
InternedString i = string_interner_insert(str, 0, hash_);
return string_interner_load(i);
}

View File

@@ -226,6 +226,7 @@ struct TypeNamed {
TYPE_KIND(Generic, struct { \
i64 id; \
String name; \
InternedString interned_name; \
Type * specialized; \
Scope * scope; \
Entity *entity; \
@@ -986,10 +987,11 @@ gb_internal Type *alloc_type(TypeKind kind) {
}
gb_internal Type *alloc_type_generic(Scope *scope, i64 id, String name, Type *specialized) {
gb_internal Type *alloc_type_generic(Scope *scope, i64 id, InternedString interned_name, Type *specialized) {
Type *t = alloc_type(Type_Generic);
t->Generic.id = id;
t->Generic.name = name;
t->Generic.name = interned_name.string();
t->Generic.interned_name = interned_name;
t->Generic.specialized = specialized;
t->Generic.scope = scope;
return t;
@@ -3569,9 +3571,9 @@ gb_internal ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y)
gb_internal Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel, bool allow_blank_ident=false);
gb_internal Selection lookup_field_with_selection(Type *type_, InternedString field_name, bool is_type, Selection sel, bool allow_blank_ident=false);
gb_internal Selection lookup_field(Type *type_, String field_name, bool is_type, bool allow_blank_ident=false) {
gb_internal Selection lookup_field(Type *type_, InternedString field_name, bool is_type, bool allow_blank_ident=false) {
return lookup_field_with_selection(type_, field_name, is_type, empty_selection, allow_blank_ident);
}
@@ -3624,13 +3626,13 @@ gb_internal Selection lookup_field_from_index(Type *type, i64 index) {
return empty_selection;
}
gb_internal Entity *scope_lookup_current(Scope *s, String const &name, u32 hash=0);
gb_internal Entity *scope_lookup_current(Scope *s, InternedString name, u32 hash=0);
gb_internal bool has_type_got_objc_class_attribute(Type *t);
gb_internal Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel, bool allow_blank_ident) {
gb_internal Selection lookup_field_with_selection(Type *type_, InternedString field_name, bool is_type, Selection sel, bool allow_blank_ident) {
GB_ASSERT(type_ != nullptr);
if (!allow_blank_ident && is_blank_ident(field_name)) {
if (!allow_blank_ident && field_name.is_blank()) {
return empty_selection;
}
@@ -3652,7 +3654,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
defer (mutex_unlock(md->mutex));
for (TypeNameObjCMetadataEntry const &entry : md->type_entries) {
GB_ASSERT(entry.entity->kind == Entity_Procedure || entry.entity->kind == Entity_ProcGroup);
if (entry.name == field_name) {
if (entry.interned == field_name) {
sel.entity = entry.entity;
sel.pseudo_field = true;
return sel;
@@ -3679,7 +3681,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
for_array(i, type->Enum.fields) {
Entity *f = type->Enum.fields[i];
GB_ASSERT(f->kind == Entity_Constant);
String str = f->token.string;
auto str = entity_interned_name(f);
if (field_name == str) {
sel.entity = f;
@@ -3730,7 +3732,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
defer (mutex_unlock(md->mutex));
for (TypeNameObjCMetadataEntry const &entry : md->value_entries) {
GB_ASSERT(entry.entity->kind == Entity_Procedure || entry.entity->kind == Entity_ProcGroup);
if (entry.name == field_name) {
if (entry.interned == field_name) {
sel.entity = entry.entity;
sel.pseudo_field = true;
return sel;
@@ -3759,7 +3761,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
continue;
}
String str = f->token.string;
auto str = entity_interned_name(f);
if (field_name == str) {
selection_add_index(&sel, i); // HACK(bill): Leaky memory
sel.entity = f;
@@ -3788,11 +3790,12 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
bool is_soa_of_array = is_soa && is_type_array(type->Struct.soa_elem);
if (is_soa_of_array) {
String mapped_field_name = {};
if (field_name == "r") mapped_field_name = str_lit("x");
else if (field_name == "g") mapped_field_name = str_lit("y");
else if (field_name == "b") mapped_field_name = str_lit("z");
else if (field_name == "a") mapped_field_name = str_lit("w");
InternedString mapped_field_name = {};
String n = field_name.string();
if (n == "r") mapped_field_name = string_interner_insert(str_lit("x"));
else if (n == "g") mapped_field_name = string_interner_insert(str_lit("y"));
else if (n == "b") mapped_field_name = string_interner_insert(str_lit("z"));
else if (n == "a") mapped_field_name = string_interner_insert(str_lit("w"));
return lookup_field_with_selection(type, mapped_field_name, is_type, sel, allow_blank_ident);
}
} else if (type->kind == Type_BitField) {
@@ -3801,7 +3804,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
continue;
}
String str = f->token.string;
auto str = entity_interned_name(f);
if (field_name == str) {
selection_add_index(&sel, i); // HACK(bill): Leaky memory
sel.entity = f;
@@ -3819,11 +3822,12 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
gb_local_persist Entity *entity__any_data = alloc_entity_field(nullptr, make_token_ident(data_str), t_rawptr, false, 0);
gb_local_persist Entity *entity__any_id = alloc_entity_field(nullptr, make_token_ident(id_str), t_typeid, false, 1);
if (field_name == data_str) {
String n = field_name.string();
if (n == data_str) {
selection_add_index(&sel, 0);
sel.entity = entity__any_data;
return sel;
} else if (field_name == id_str) {
} else if (n == id_str) {
selection_add_index(&sel, 1);
sel.entity = entity__any_id;
return sel;
@@ -3841,19 +3845,21 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
gb_local_persist Entity *entity__x = alloc_entity_field(nullptr, make_token_ident(x), t_f16, false, 0);
gb_local_persist Entity *entity__y = alloc_entity_field(nullptr, make_token_ident(y), t_f16, false, 1);
gb_local_persist Entity *entity__z = alloc_entity_field(nullptr, make_token_ident(z), t_f16, false, 2);
if (field_name == w) {
String n = field_name.string();
if (n == w) {
selection_add_index(&sel, 3);
sel.entity = entity__w;
return sel;
} else if (field_name == x) {
} else if (n == x) {
selection_add_index(&sel, 0);
sel.entity = entity__x;
return sel;
} else if (field_name == y) {
} else if (n == y) {
selection_add_index(&sel, 1);
sel.entity = entity__y;
return sel;
} else if (field_name == z) {
} else if (n == z) {
selection_add_index(&sel, 2);
sel.entity = entity__z;
return sel;
@@ -3870,19 +3876,21 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
gb_local_persist Entity *entity__x = alloc_entity_field(nullptr, make_token_ident(x), t_f32, false, 0);
gb_local_persist Entity *entity__y = alloc_entity_field(nullptr, make_token_ident(y), t_f32, false, 1);
gb_local_persist Entity *entity__z = alloc_entity_field(nullptr, make_token_ident(z), t_f32, false, 2);
if (field_name == w) {
String n = field_name.string();
if (n == w) {
selection_add_index(&sel, 3);
sel.entity = entity__w;
return sel;
} else if (field_name == x) {
} else if (n == x) {
selection_add_index(&sel, 0);
sel.entity = entity__x;
return sel;
} else if (field_name == y) {
} else if (n == y) {
selection_add_index(&sel, 1);
sel.entity = entity__y;
return sel;
} else if (field_name == z) {
} else if (n == z) {
selection_add_index(&sel, 2);
sel.entity = entity__z;
return sel;
@@ -3899,19 +3907,21 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
gb_local_persist Entity *entity__x = alloc_entity_field(nullptr, make_token_ident(x), t_f64, false, 0);
gb_local_persist Entity *entity__y = alloc_entity_field(nullptr, make_token_ident(y), t_f64, false, 1);
gb_local_persist Entity *entity__z = alloc_entity_field(nullptr, make_token_ident(z), t_f64, false, 2);
if (field_name == w) {
String n = field_name.string();
if (n == w) {
selection_add_index(&sel, 3);
sel.entity = entity__w;
return sel;
} else if (field_name == x) {
} else if (n == x) {
selection_add_index(&sel, 0);
sel.entity = entity__x;
return sel;
} else if (field_name == y) {
} else if (n == y) {
selection_add_index(&sel, 1);
sel.entity = entity__y;
return sel;
} else if (field_name == z) {
} else if (n == z) {
selection_add_index(&sel, 2);
sel.entity = entity__z;
return sel;
@@ -3928,19 +3938,21 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
gb_local_persist Entity *entity__x = alloc_entity_field(nullptr, make_token_ident(x), t_untyped_float, false, 0);
gb_local_persist Entity *entity__y = alloc_entity_field(nullptr, make_token_ident(y), t_untyped_float, false, 1);
gb_local_persist Entity *entity__z = alloc_entity_field(nullptr, make_token_ident(z), t_untyped_float, false, 2);
if (field_name == w) {
String n = field_name.string();
if (n == w) {
selection_add_index(&sel, 3);
sel.entity = entity__w;
return sel;
} else if (field_name == x) {
} else if (n == x) {
selection_add_index(&sel, 0);
sel.entity = entity__x;
return sel;
} else if (field_name == y) {
} else if (n == y) {
selection_add_index(&sel, 1);
sel.entity = entity__y;
return sel;
} else if (field_name == z) {
} else if (n == z) {
selection_add_index(&sel, 2);
sel.entity = entity__z;
return sel;
@@ -3955,7 +3967,8 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
String allocator_str = str_lit("allocator");
gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 3);
if (field_name == allocator_str) {
String n = field_name.string();
if (n == allocator_str) {
selection_add_index(&sel, 3);
sel.entity = entity__allocator;
return sel;
@@ -3965,7 +3978,8 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
String allocator_str = str_lit("allocator");
gb_local_persist Entity *entity__allocator = alloc_entity_field(nullptr, make_token_ident(allocator_str), t_allocator, false, 2);
if (field_name == allocator_str) {
String n = field_name.string();
if (n == allocator_str) {
selection_add_index(&sel, 2);
sel.entity = entity__allocator;
return sel;
@@ -3973,7 +3987,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
#define _ARRAY_FIELD_CASE_IF(_length, _name) \
if (field_name == (_name)) { \
if (n == (_name)) { \
selection_add_index(&sel, (_length)-1); \
sel.entity = alloc_entity_array_elem(nullptr, make_token_ident(str_lit(_name)), elem, (_length)-1); \
return sel; \
@@ -3986,7 +4000,7 @@ case (_length): \
} else if (type->kind == Type_Array) {
String n = field_name.string();
Type *elem = type->Array.elem;
if (type->Array.count <= 4) {
@@ -4001,8 +4015,9 @@ case (_length): \
}
}
} else if (type->kind == Type_SimdVector) {
String n = field_name.string();
Type *elem = type->SimdVector.elem;
if (type->SimdVector.count <= 4) {
// HACK(bill): Memory leak
switch (type->SimdVector.count) {