Browse Source

Clean up rules for name mangling

gingerBill 6 months ago
parent
commit
043f9aea61
2 changed files with 64 additions and 179 deletions
  1. 4 158
      src/llvm_backend_general.cpp
  2. 60 21
      src/name_canonicalization.cpp

+ 4 - 158
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<u32> 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));
 
-	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 = {};
+	gb_printf_err("%s\n", w);
 
-	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);
+	String name = copy_string(permanent_allocator(), make_string(cast(u8 const *)w, gb_string_length(w)));
 
-		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;

+ 60 - 21
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: