diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 6ff166899..7fdfa0bb2 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1443,129 +1443,6 @@ gb_internal void lb_clone_struct_type(LLVMTypeRef dst, LLVMTypeRef src) { LLVMStructSetBody(dst, fields, field_count, LLVMIsPackedStruct(src)); } -gb_internal String lb_mangle_name(Entity *e) { -#if 1 - String name = e->token.string; - - AstPackage *pkg = e->pkg; - GB_ASSERT_MSG(pkg != nullptr, "Missing package for '%.*s'", LIT(name)); - String pkgn = pkg->name; - GB_ASSERT(!rune_is_digit(pkgn[0])); - if (pkgn == "llvm") { - pkgn = str_lit("llvm$"); - } - - isize max_len = pkgn.len + 1 + name.len + 1; - bool require_suffix_id = is_type_polymorphic(e->type, true); - - if ((e->scope->flags & (ScopeFlag_File | ScopeFlag_Pkg)) == 0) { - require_suffix_id = true; - } else if (is_blank_ident(e->token)) { - require_suffix_id = true; - }if (e->flags & EntityFlag_NotExported) { - require_suffix_id = true; - } - - if (require_suffix_id) { - max_len += 21; - } - - char *new_name = gb_alloc_array(permanent_allocator(), char, max_len); - isize new_name_len = gb_snprintf( - new_name, max_len, - "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s", LIT(pkgn), LIT(name) - ); - if (require_suffix_id) { - char *str = new_name + new_name_len-1; - isize len = max_len-new_name_len; - isize extra = gb_snprintf(str, len, "-%llu", cast(unsigned long long)e->id); - new_name_len += extra-1; - } - - String mangled_name = make_string((u8 const *)new_name, new_name_len-1); - return mangled_name; -#else - gbString w = gb_string_make(gb_heap_allocator(), ""); - w = write_canonical_entity_name(w, e); - gb_printf_err(">> %s\n", w); - - String mangled_name = make_string(cast(u8 const *)w, gb_string_length(w)); - return mangled_name; -#endif -} - -gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedure *p, lbModule *module) { -#if 0 - // NOTE(bill, 2020-03-08): A polymorphic procedure may take a nested type declaration - // and as a result, the declaration does not have time to determine what it should be - - GB_ASSERT(e != nullptr && e->kind == Entity_TypeName); - if (e->TypeName.ir_mangled_name.len != 0) { - return e->TypeName.ir_mangled_name; - } - GB_ASSERT((e->scope->flags & ScopeFlag_File) == 0); - - if (p == nullptr) { - Entity *proc = nullptr; - if (e->parent_proc_decl != nullptr) { - proc = e->parent_proc_decl->entity; - } else { - Scope *scope = e->scope; - while (scope != nullptr && (scope->flags & ScopeFlag_Proc) == 0) { - scope = scope->parent; - } - GB_ASSERT(scope != nullptr); - GB_ASSERT(scope->flags & ScopeFlag_Proc); - proc = scope->procedure_entity; - } - if (proc != nullptr) { - GB_ASSERT(proc->kind == Entity_Procedure); - if (proc->code_gen_procedure != nullptr) { - p = proc->code_gen_procedure; - } - } - } - - - // NOTE(bill): Generate a new name - // parent_proc.name-guid - String ts_name = e->token.string; - - if (p != nullptr) { - isize name_len = p->name.len + 1 + ts_name.len + 1 + 10 + 1; - char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); - u32 guid = 1+p->module->nested_type_name_guid.fetch_add(1); - name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(p->name), LIT(ts_name), guid); - - String name = make_string(cast(u8 *)name_text, name_len-1); - e->TypeName.ir_mangled_name = name; - - { - String s = type_to_canonical_string(temporary_allocator(), e->type); - gb_printf_err("1) %.*s\n", LIT(s)); - gb_printf_err("2) %.*s\n", LIT(name)); - } - return name; - } else { - // NOTE(bill): a nested type be required before its parameter procedure exists. Just give it a temp name for now - isize name_len = 9 + 1 + ts_name.len + 1 + 10 + 1; - char *name_text = gb_alloc_array(permanent_allocator(), char, name_len); - static std::atomic guid; - name_len = gb_snprintf(name_text, name_len, "_internal" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(ts_name), 1+guid.fetch_add(1)); - - String name = make_string(cast(u8 *)name_text, name_len-1); - e->TypeName.ir_mangled_name = name; - - { - String s = type_to_canonical_string(temporary_allocator(), e->type); - gb_printf_err("3) %.*s\n", LIT(s)); - gb_printf_err("4) %.*s\n", LIT(name)); - } - return name; - } -#endif -} - gb_internal String lb_get_entity_name(lbModule *m, Entity *e) { GB_ASSERT(m != nullptr); GB_ASSERT(e != nullptr); @@ -1579,51 +1456,20 @@ gb_internal String lb_get_entity_name(lbModule *m, Entity *e) { return e->token.string; } -#if 1 gbString w = gb_string_make(heap_allocator(), ""); w = write_canonical_entity_name(w, e); defer (gb_string_free(w)); + gb_printf_err("%s\n", w); + String name = copy_string(permanent_allocator(), make_string(cast(u8 const *)w, gb_string_length(w))); -#else - if (e->kind == Entity_TypeName && (e->scope->flags & ScopeFlag_File) == 0) { - return lb_set_nested_type_name_ir_mangled_name(e, nullptr, m); - } - String name = {}; - - bool no_name_mangle = false; - - if (e->kind == Entity_Variable) { - bool is_foreign = e->Variable.is_foreign; - bool is_export = e->Variable.is_export; - no_name_mangle = e->Variable.link_name.len > 0 || is_foreign || is_export; - if (e->Variable.link_name.len > 0) { - return e->Variable.link_name; - } - } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) { - return e->Procedure.link_name; - } else if (e->kind == Entity_Procedure && e->Procedure.is_export) { - no_name_mangle = true; - } - - if (!no_name_mangle) { - name = lb_mangle_name(e); - - gbString w = gb_string_make(gb_heap_allocator(), ""); - w = write_canonical_entity_name(w, e); - if (w[0] == 0) { - gb_printf_err(">> %s %.*s\n", w, LIT(name)); - } - } - if (name.len == 0) { - name = e->token.string; - } -#endif if (e->kind == Entity_TypeName) { e->TypeName.ir_mangled_name = name; } else if (e->kind == Entity_Procedure) { e->Procedure.link_name = name; + } else if (e->kind == Entity_Variable) { + e->Variable.link_name = name; } return name; diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index 48f7a18cb..3910c573d 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -1,3 +1,43 @@ +/* + General Rules for canonical name mangling + + * No spaces between any values + + * normal declarations - pkg.name + * builtin names - just their normal name e.g. `i32` or `string` + * nested - pkg.parent1.parent2.name + * file private - pkg.[file_name].name + * Example: `foo.[bar.odin].Type` + * polymorphic procedure/type - pkg.foo::TYPE + * naming convention for parameters + * type + * $typeid_based_name + * $$constant_parameter + * Example: `foo.to_thing::proc(u64)->([]u8)` + * nested decl in polymorphic procedure - pkg.foo::TYPE.name + * anonymous procedures - pkg.foo.$anon123 + * 123 is the file offset in bytes + + +*/ + +#define CANONICAL_TYPE_SEPARATOR ":" +#define CANONICAL_NAME_SEPARATOR "." + +#define CANONICAL_PARAM_SEPARATOR "," + +#define CANONICAL_PARAM_TYPEID "$" +#define CANONICAL_PARAM_CONST "$$" + +#define CANONICAL_PARAM_C_VARARG "#c_vararg" +#define CANONICAL_PARAM_VARARG ".." + +#define CANONICAL_FIELD_SEPARATOR "," + +#define CANONICAL_ANON_PREFIX "$anon" + +#define CANONICAL_NONE_TYPE "<>" + gb_internal gbString write_type_to_canonical_string(gbString w, Type *type); gb_internal gbString write_canonical_params(gbString w, Type *params) { w = gb_string_appendc(w, "("); @@ -6,25 +46,25 @@ gb_internal gbString write_canonical_params(gbString w, Type *params) { for_array(i, params->Tuple.variables) { Entity *v = params->Tuple.variables[i]; if (i > 0) { - w = gb_string_appendc(w, ","); + w = gb_string_appendc(w, CANONICAL_PARAM_SEPARATOR); } if (v->kind == Entity_Variable) { if (v->flags&EntityFlag_CVarArg) { - w = gb_string_appendc(w, "#c_vararg"); + w = gb_string_appendc(w, CANONICAL_PARAM_C_VARARG); } if (v->flags&EntityFlag_Ellipsis) { Type *slice = base_type(v->type); - w = gb_string_appendc(w, ".."); + w = gb_string_appendc(w, CANONICAL_PARAM_VARARG); GB_ASSERT(v->type->kind == Type_Slice); w = write_type_to_canonical_string(w, slice->Slice.elem); } else { w = write_type_to_canonical_string(w, v->type); } } else if (v->kind == Entity_TypeName) { - w = gb_string_appendc(w, "$"); + w = gb_string_appendc(w, CANONICAL_PARAM_TYPEID); w = write_type_to_canonical_string(w, v->type); } else if (v->kind == Entity_Constant) { - w = gb_string_appendc(w, "$$"); + w = gb_string_appendc(w, CANONICAL_PARAM_CONST); w = write_exact_value_to_string(w, v->Constant.value); } else { GB_PANIC("TODO(bill): handle non type/const parapoly parameter values"); @@ -88,24 +128,24 @@ gb_internal gbString write_canonical_parent_prefix(gbString w, Entity *e, bool i w = write_canonical_parent_prefix(w, p); w = gb_string_append_length(w, p->token.string.text, p->token.string.len); if (is_type_polymorphic(p->type)) { - w = gb_string_appendc(w, "::"); + w = gb_string_appendc(w, CANONICAL_TYPE_SEPARATOR); w = write_type_to_canonical_string(w, p->type); } - w = gb_string_appendc(w, "."); + w = gb_string_appendc(w, CANONICAL_NAME_SEPARATOR); } else if (e->pkg && (scope_lookup_current(e->pkg->scope, e->token.string) == e)) { w = gb_string_append_length(w, e->pkg->name.text, e->pkg->name.len); if (e->pkg->name == "llvm") { gb_string_appendc(w, "$"); } - w = gb_string_appendc(w, "."); + w = gb_string_appendc(w, CANONICAL_NAME_SEPARATOR); } else { String file_name = filename_without_directory(e->file->fullpath); w = gb_string_append_length(w, e->pkg->name.text, e->pkg->name.len); if (e->pkg->name == "llvm") { gb_string_appendc(w, "$"); } - w = gb_string_appendc(w, gb_bprintf(".[%.*s].", LIT(file_name))); + w = gb_string_appendc(w, gb_bprintf(CANONICAL_NAME_SEPARATOR "[%.*s]" CANONICAL_NAME_SEPARATOR, LIT(file_name))); } } else if (e->kind == Entity_Procedure) { if (e->Procedure.is_export || e->Procedure.is_foreign) { @@ -116,17 +156,17 @@ gb_internal gbString write_canonical_parent_prefix(gbString w, Entity *e, bool i } if (e->kind == Entity_Procedure && e->Procedure.is_anonymous) { - w = gb_string_appendc(w, gb_bprintf("$anon%d", e->token.pos.offset)); + w = gb_string_appendc(w, gb_bprintf(CANONICAL_ANON_PREFIX "%d", e->token.pos.offset)); } else { w = gb_string_append_length(w, e->token.string.text, e->token.string.len); } if (is_type_polymorphic(e->type)) { - w = gb_string_appendc(w, "::"); + w = gb_string_appendc(w, CANONICAL_TYPE_SEPARATOR); w = write_type_to_canonical_string(w, e->type); } if (!ignore_final_dot) { - w = gb_string_appendc(w, "."); + w = gb_string_appendc(w, CANONICAL_NAME_SEPARATOR); } return w; @@ -177,7 +217,7 @@ gb_internal gbString write_canonical_entity_name(gbString w, Entity *e) { if (e->pkg->name == "llvm") { gb_string_appendc(w, "$"); } - w = gb_string_appendc(w, gb_bprintf(".[%.*s].", LIT(file_name))); + w = gb_string_appendc(w, gb_bprintf(CANONICAL_NAME_SEPARATOR "[%.*s]" CANONICAL_NAME_SEPARATOR, LIT(file_name))); goto write_base_name; } gb_printf_err("%s WEIRD ENTITY TYPE %s %u %p\n", token_pos_to_string(e->token.pos), type_to_string(e->type), s->flags, s->decl_info); @@ -186,7 +226,7 @@ gb_internal gbString write_canonical_entity_name(gbString w, Entity *e) { } if (e->pkg != nullptr) { w = gb_string_append_length(w, e->pkg->name.text, e->pkg->name.len); - w = gb_string_appendc(w, "."); + w = gb_string_appendc(w, CANONICAL_NAME_SEPARATOR); } write_base_name: @@ -210,7 +250,7 @@ write_base_name: case Entity_Variable: w = gb_string_append_length(w, e->token.string.text, e->token.string.len); if (is_type_polymorphic(e->type)) { - w = gb_string_appendc(w, "::"); + w = gb_string_appendc(w, CANONICAL_TYPE_SEPARATOR); w = write_type_to_canonical_string(w, e->type); } return w; @@ -225,7 +265,7 @@ write_base_name: // NOTE(bill): This exists so that we deterministically hash a type by serializing it to a canonical string gb_internal gbString write_type_to_canonical_string(gbString w, Type *type) { if (type == nullptr) { - return gb_string_appendc(w, "<>"); // none/void type + return gb_string_appendc(w, CANONICAL_NONE_TYPE); // none/void type } type = default_type(type); @@ -287,7 +327,7 @@ gb_internal gbString write_type_to_canonical_string(gbString w, Type *type) { Entity *f = type->Enum.fields[i]; GB_ASSERT(f->kind == Entity_Constant); if (i > 0) { - w = gb_string_appendc(w, ","); + w = gb_string_appendc(w, CANONICAL_FIELD_SEPARATOR); } w = gb_string_append_length(w, f->token.string.text, f->token.string.len); w = gb_string_appendc(w, "="); @@ -324,7 +364,7 @@ gb_internal gbString write_type_to_canonical_string(gbString w, Type *type) { w = gb_string_appendc(w, "{"); for_array(i, type->Union.variants) { Type *t = type->Union.variants[i]; - if (i > 0) w = gb_string_appendc(w, ", "); + if (i > 0) w = gb_string_appendc(w, CANONICAL_FIELD_SEPARATOR); w = write_type_to_canonical_string(w, t); } return gb_string_appendc(w, "}"); @@ -351,7 +391,7 @@ gb_internal gbString write_type_to_canonical_string(gbString w, Type *type) { Entity *f = type->Struct.fields[i]; GB_ASSERT(f->kind == Entity_Variable); if (i > 0) { - w = gb_string_appendc(w, ","); + w = gb_string_appendc(w, CANONICAL_FIELD_SEPARATOR); } w = gb_string_append_length (w, f->token.string.text, f->token.string.len); w = gb_string_appendc (w, ":"); @@ -372,7 +412,7 @@ gb_internal gbString write_type_to_canonical_string(gbString w, Type *type) { for (isize i = 0; i < type->BitField.fields.count; i++) { Entity *f = type->BitField.fields[i]; if (i > 0) { - w = gb_string_appendc(w, ","); + w = gb_string_appendc(w, CANONICAL_FIELD_SEPARATOR); } w = gb_string_append_length(w, f->token.string.text, f->token.string.len); w = gb_string_appendc(w, ":"); @@ -407,7 +447,6 @@ gb_internal gbString write_type_to_canonical_string(gbString w, Type *type) { } else { w = gb_string_append_length(w, type->Named.name.text, type->Named.name.len); } - // Handle parapoly stuff here? return w; default: