Browse Source

Clean up name mangling by using unique package names per project

gingerBill 7 years ago
parent
commit
547a2831c7
10 changed files with 141 additions and 88 deletions
  1. 1 1
      core/mem/alloc.odin
  2. 39 4
      core/mem/mem.odin
  3. 7 8
      core/runtime/core.odin
  4. 0 47
      core/runtime/internal.odin
  5. 12 11
      src/checker.cpp
  6. 2 1
      src/checker.hpp
  7. 56 11
      src/ir.cpp
  8. 16 0
      src/parser.cpp
  9. 1 0
      src/parser.hpp
  10. 7 5
      src/unicode.cpp

+ 1 - 1
core/mem/alloc.odin

@@ -62,7 +62,7 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
 	new_memory := alloc(new_size, alignment, loc);
 	if new_memory == nil do return nil;
 
-	__mem_copy(new_memory, old_memory, min(old_size, new_size));;
+	copy(new_memory, old_memory, min(old_size, new_size));;
 	free(old_memory, loc);
 	return new_memory;
 }

+ 39 - 4
core/mem/mem.odin

@@ -11,16 +11,51 @@ swap :: proc[swap16, swap32, swap64];
 
 
 set :: proc "contextless" (data: rawptr, value: i32, len: int) -> rawptr {
-	return __mem_set(data, value, len);
+	if data == nil do return nil;
+	foreign __llvm_core {
+		when size_of(rawptr) == 8 {
+			@(link_name="llvm.memset.p0i8.i64")
+			llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
+		} else {
+			@(link_name="llvm.memset.p0i8.i32")
+			llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
+		}
+	}
+	llvm_memset(data, byte(value), len, 1, false);
+	return data;
 }
 zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
-	return __mem_zero(data, len);
+	return set(data, 0, len);
 }
 copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
-	return __mem_copy(dst, src, len);
+	if src == nil do return dst;
+	// NOTE(bill): This _must_ be implemented like C's memmove
+	foreign __llvm_core {
+		when size_of(rawptr) == 8 {
+			@(link_name="llvm.memmove.p0i8.p0i8.i64")
+			llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
+		} else {
+			@(link_name="llvm.memmove.p0i8.p0i8.i32")
+			llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
+		}
+	}
+	llvm_memmove(dst, src, len, 1, false);
+	return dst;
 }
 copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
-	return __mem_copy_non_overlapping(dst, src, len);
+	if src == nil do return dst;
+	// NOTE(bill): This _must_ be implemented like C's memcpy
+	foreign __llvm_core {
+		when size_of(rawptr) == 8 {
+			@(link_name="llvm.memcpy.p0i8.p0i8.i64")
+	 		llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
+		} else {
+			@(link_name="llvm.memcpy.p0i8.p0i8.i32")
+	 		llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
+		}
+	}
+	llvm_memcpy(dst, src, len, 1, false);
+	return dst;
 }
 compare :: proc "contextless" (a, b: []byte) -> int {
 	return compare_byte_ptrs(&a[0], &b[0], min(len(a), len(b)));

+ 7 - 8
core/runtime/core.odin

@@ -153,7 +153,6 @@ Allocator_Mode :: enum byte {
 	Resize,
 }
 
-
 Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
 	                         size, alignment: int,
 	                         old_memory: rawptr, old_size: int, flags: u64 = 0, location := #caller_location) -> rawptr;
@@ -310,7 +309,7 @@ __init_context :: proc "contextless" (c: ^Context) {
 
 copy :: proc "contextless" (dst, src: $T/[]$E) -> int {
 	n := max(0, min(len(dst), len(src)));
-	if n > 0 do __mem_copy(&dst[0], &src[0], n*size_of(E));
+	if n > 0 do mem.copy(&dst[0], &src[0], n*size_of(E));
 	return n;
 }
 
@@ -390,7 +389,7 @@ append :: proc(array: ^$T/[dynamic]$E, args: ...E, loc := #caller_location) -> i
 		a := (^raw.Dynamic_Array)(array);
 		data := (^E)(a.data);
 		assert(data != nil);
-		__mem_copy(mem.ptr_offset(data, uintptr(a.len)), &args[0], size_of(E) * arg_len);
+		mem.copy(mem.ptr_offset(data, uintptr(a.len)), &args[0], size_of(E) * arg_len);
 		a.len += arg_len;
 	}
 	return len(array);
@@ -531,7 +530,7 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
 	assert(array.data != nil);
 	data := uintptr(array.data) + uintptr(elem_size*array.len);
 
-	__mem_copy(rawptr(data), items, elem_size * item_count);
+	mem.copy(rawptr(data), items, elem_size * item_count);
 	array.len += item_count;
 	return array.len;
 }
@@ -549,7 +548,7 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in
 
 	assert(array.data != nil);
 	data := uintptr(array.data) + uintptr(elem_size*array.len);
-	__mem_zero(rawptr(data), elem_size);
+	mem.zero(rawptr(data), elem_size);
 	array.len += 1;
 	return array.len;
 }
@@ -655,7 +654,7 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc :=
 		e := __dynamic_map_get_entry(new_header, j);
 		e.next = fr.entry_index;
 		ndata := uintptr(e);
-		__mem_copy(rawptr(ndata+value_offset), rawptr(data+value_offset), value_size);
+		mem.copy(rawptr(ndata+value_offset), rawptr(data+value_offset), value_size);
 
 		if __dynamic_map_full(new_header) do __dynamic_map_grow(new_header, loc);
 	}
@@ -699,7 +698,7 @@ __dynamic_map_set :: proc(h: __Map_Header, key: __Map_Key, value: rawptr, loc :=
 		e := __dynamic_map_get_entry(h, index);
 		e.key = key;
 		val := (^byte)(uintptr(e) + h.value_offset);
-		__mem_copy(val, value, h.value_size);
+		mem.copy(val, value, h.value_size);
 	}
 
 	if __dynamic_map_full(h) {
@@ -772,7 +771,7 @@ __dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) #no_bo
 		__dynamic_map_get_entry(h, fr.entry_prev).next = __dynamic_map_get_entry(h, fr.entry_index).next;
 	}
 
-	__mem_copy(__dynamic_map_get_entry(h, fr.entry_index), __dynamic_map_get_entry(h, m.entries.len-1), entry_size);
+	mem.copy(__dynamic_map_get_entry(h, fr.entry_index), __dynamic_map_get_entry(h, m.entries.len-1), entry_size);
 	last := __dynamic_map_find(h, __dynamic_map_get_entry(h, fr.entry_index).key);
 	if last.entry_prev >= 0 {
 		__dynamic_map_get_entry(h, last.entry_prev).next = fr.entry_index;

+ 0 - 47
core/runtime/internal.odin

@@ -318,53 +318,6 @@ __slice_expr_error_loc :: inline proc "contextless" (using loc := #caller_locati
 	__slice_expr_error(file_path, int(line), int(column), lo, hi, len);
 }
 
-__mem_set :: proc "contextless" (data: rawptr, value: i32, len: int) -> rawptr {
-	if data == nil do return nil;
-	foreign __llvm_core {
-		when size_of(rawptr) == 8 {
-			@(link_name="llvm.memset.p0i8.i64")
-			llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
-		} else {
-			@(link_name="llvm.memset.p0i8.i32")
-			llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---;
-		}
-	}
-	llvm_memset(data, byte(value), len, 1, false);
-	return data;
-}
-__mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
-	return __mem_set(data, 0, len);
-}
-__mem_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
-	if src == nil do return dst;
-	// NOTE(bill): This _must_ be implemented like C's memmove
-	foreign __llvm_core {
-		when size_of(rawptr) == 8 {
-			@(link_name="llvm.memmove.p0i8.p0i8.i64")
-			llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
-		} else {
-			@(link_name="llvm.memmove.p0i8.p0i8.i32")
-			llvm_memmove :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
-		}
-	}
-	llvm_memmove(dst, src, len, 1, false);
-	return dst;
-}
-__mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
-	if src == nil do return dst;
-	// NOTE(bill): This _must_ be implemented like C's memcpy
-	foreign __llvm_core {
-		when size_of(rawptr) == 8 {
-			@(link_name="llvm.memcpy.p0i8.p0i8.i64")
-	 		llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
-		} else {
-			@(link_name="llvm.memcpy.p0i8.p0i8.i32")
-	 		llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) ---;
-		}
-	}
-	llvm_memcpy(dst, src, len, 1, false);
-	return dst;
-}
 
 
 @(default_calling_convention = "c")

+ 12 - 11
src/checker.cpp

@@ -1350,7 +1350,6 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
 	ptr_set_init(&c->info.minimum_dependency_type_info_set, heap_allocator());
 
 	String required_builtin_entities[] = {
-		str_lit("__mem_zero"),
 		str_lit("__init_context"),
 
 		str_lit("__args__"),
@@ -1362,12 +1361,13 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
 		str_lit("Context"),
 	};
 	for (isize i = 0; i < gb_count_of(required_builtin_entities); i++) {
-		add_dependency_to_set(c, scope_lookup_entity(c->runtime_package->scope, required_builtin_entities[i]));
+		add_dependency_to_set(c, scope_lookup_entity(c->info.runtime_package->scope, required_builtin_entities[i]));
 	}
 
 	AstPackage *mem = get_core_package(&c->info, str_lit("mem"));
 	String required_mem_entities[] = {
 		str_lit("default_allocator"),
+		str_lit("zero"),
 	};
 	for (isize i = 0; i < gb_count_of(required_mem_entities); i++) {
 		add_dependency_to_set(c, scope_lookup_entity(mem->scope, required_mem_entities[i]));
@@ -1380,7 +1380,7 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
 			str_lit("__dynamic_array_expr_error"),
 		};
 		for (isize i = 0; i < gb_count_of(bounds_check_entities); i++) {
-			add_dependency_to_set(c, scope_lookup_entity(c->runtime_package->scope, bounds_check_entities[i]));
+			add_dependency_to_set(c, scope_lookup_entity(c->info.runtime_package->scope, bounds_check_entities[i]));
 		}
 	}
 
@@ -1500,7 +1500,7 @@ Array<EntityGraphNode *> generate_entity_dependency_graph(CheckerInfo *info) {
 
 
 Entity *find_core_entity(Checker *c, String name) {
-	Entity *e = current_scope_lookup_entity(c->runtime_package->scope, name);
+	Entity *e = current_scope_lookup_entity(c->info.runtime_package->scope, name);
 	if (e == nullptr) {
 		compiler_error("Could not find type declaration for '%.*s'\n"
 		               "Is '_preload.odin' missing from the 'core' directory relative to odin.exe?", LIT(name));
@@ -1510,7 +1510,7 @@ Entity *find_core_entity(Checker *c, String name) {
 }
 
 Type *find_core_type(Checker *c, String name) {
-	Entity *e = current_scope_lookup_entity(c->runtime_package->scope, name);
+	Entity *e = current_scope_lookup_entity(c->info.runtime_package->scope, name);
 	if (e == nullptr) {
 		compiler_error("Could not find type declaration for '%.*s'\n"
 		               "Is '_preload.odin' missing from the 'core' directory relative to odin.exe?", LIT(name));
@@ -2513,10 +2513,11 @@ void check_add_import_decl(Checker *c, AstNodeImportDecl *id) {
 	Scope *scope = *found;
 	GB_ASSERT(scope->is_package && scope->package != nullptr);
 
-	if (scope->is_global) {
-		error(token, "Importing a built-in package is disallowed and unnecessary");
-		return;
-	}
+	// TODO(bill): Should this be allowed or not?
+	// if (scope->is_global) {
+	// 	error(token, "Importing a runtime package is disallowed and unnecessary");
+	// 	return;
+	// }
 
 	if (ptr_set_exists(&parent_scope->imported, scope)) {
 		// error(token, "Multiple import of the same file within this scope");
@@ -2926,8 +2927,8 @@ void check_parsed_files(Checker *c) {
 			c->info.init_scope = scope;
 		}
 		if (p->kind == Package_Runtime) {
-			GB_ASSERT(c->runtime_package == nullptr);
-			c->runtime_package = p;
+			GB_ASSERT(c->info.runtime_package == nullptr);
+			c->info.runtime_package = p;
 		}
 	}
 

+ 2 - 1
src/checker.hpp

@@ -313,6 +313,8 @@ struct CheckerInfo {
 	Array<Type *>         type_info_types;
 	Map<isize>            type_info_map;   // Key: Type *
 
+
+	AstPackage *          runtime_package;
 	Scope *               init_scope;
 	Entity *              entry_point;
 	PtrSet<Entity *>      minimum_dependency_set;
@@ -326,7 +328,6 @@ struct Checker {
 
 
 	AstFile *                  curr_ast_file;
-	AstPackage *               runtime_package;
 	// NOTE(bill): Procedures to check
 	Array<ProcedureInfo>       procs;
 	Map<Scope *>               package_scopes; // Key: String (fullpath)

+ 56 - 11
src/ir.cpp

@@ -1575,8 +1575,9 @@ void ir_emit_zero_init(irProcedure *p, irValue *address, AstNode *expr) {
 	auto args = array_make<irValue *>(a, 2);
 	args[0] = ir_emit_conv(p, address, t_rawptr);
 	args[1] = ir_const_int(a, type_size_of(t));
-	if (p->entity->token.string != "__mem_zero") {
-		ir_emit_global_call(p, "__mem_zero", args, expr);
+	AstPackage *package = get_core_package(p->module->info, str_lit("mem"));
+	if (p->entity->token.string != "zero" && p->entity->package != package) {
+		ir_emit_package_call(p, "mem", "zero", args, expr);
 	}
 	ir_emit(p, ir_instr_zero_init(p, address));
 }
@@ -1701,7 +1702,10 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> args) {
 
 irValue *ir_emit_global_call(irProcedure *proc, char const *name_, Array<irValue *> args, AstNode *expr) {
 	String name = make_string_c(cast(char *)name_);
-	irValue **found = map_get(&proc->module->members, hash_string(name));
+
+	AstPackage *p = proc->module->info->runtime_package;
+	Entity *e = current_scope_lookup_entity(p->scope, name);
+	irValue **found = map_get(&proc->module->values, hash_entity(e));
 	GB_ASSERT_MSG(found != nullptr, "%.*s", LIT(name));
 	irValue *gp = *found;
 	irValue *call = ir_emit_call(proc, gp, args);
@@ -3771,13 +3775,15 @@ void ir_emit_dynamic_array_bounds_check(irProcedure *proc, Token token, irValue
 ////////////////////////////////////////////////////////////////
 
 String ir_mangle_name(irGen *s, Entity *e) {
+	irModule *m = &s->module;
+	CheckerInfo *info = m->info;
+	gbAllocator a = m->allocator;
+
+#if 0
 	// NOTE(bill): prefix names not in the init scope
 	// TODO(bill): make robust and not just rely on the file's name
 	String path = e->token.pos.file;
 	String name = e->token.string;
-	irModule *m = &s->module;
-	CheckerInfo *info = m->info;
-	gbAllocator a = m->allocator;
 	AstFile *file = ast_file_of_filename(info, path);
 
 	char *str = gb_alloc_array(a, char, path.len+1);
@@ -3825,6 +3831,35 @@ String ir_mangle_name(irGen *s, Entity *e) {
 	}
 
 	return make_string(new_name, new_name_len-1);
+
+#else
+	GB_ASSERT(e->package != nullptr);
+	String pkg = e->package->name;
+	GB_ASSERT(!rune_is_digit(pkg[0]));
+
+	String name = e->token.string;
+
+
+	isize max_len = pkg.len + 1 + name.len + 1;
+	bool require_suffix_id = is_type_polymorphic(e->type);
+	if (require_suffix_id) {
+		max_len += 21;
+	}
+
+	u8 *new_name = gb_alloc_array(a, u8, max_len);
+	isize new_name_len = gb_snprintf(
+		cast(char *)new_name, max_len,
+		"%.*s.%.*s", LIT(pkg), LIT(name)
+	);
+	if (require_suffix_id) {
+		char *str = cast(char *)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;
+	}
+
+	return make_string(new_name, new_name_len-1);
+#endif
 }
 
 
@@ -4060,7 +4095,9 @@ irValue *ir_emit_clamp(irProcedure *proc, Type *t, irValue *x, irValue *min, irV
 
 
 irValue *ir_find_global_variable(irProcedure *proc, String name) {
-	irValue **value = map_get(&proc->module->members, hash_string(name));
+	AstPackage *pkg = proc->module->info->runtime_package;
+	Entity *e = current_scope_lookup_entity(pkg->scope, name);
+	irValue **value = map_get(&proc->module->values, hash_entity(e));
 	GB_ASSERT_MSG(value != nullptr, "Unable to find global variable '%.*s'", LIT(name));
 	return *value;
 }
@@ -8325,12 +8362,9 @@ void ir_gen_tree(irGen *s) {
 			}
 			GB_ASSERT(e->kind == Entity_Variable);
 
-
-			bool is_global = e->package != nullptr;
-
 			bool is_foreign = e->Variable.is_foreign;
 			bool is_export  = e->Variable.is_export;
-			bool no_name_mangle = is_global || e->Variable.link_name.len > 0 || is_foreign || is_export;
+			bool no_name_mangle = e->Variable.link_name.len > 0 || is_foreign || is_export;
 
 			String name = e->token.string;
 			if (!no_name_mangle) {
@@ -8401,6 +8435,7 @@ void ir_gen_tree(irGen *s) {
 
 		String original_name = name;
 
+	#if 0
 		if (!package_scope->is_global || polymorphic_struct || is_type_polymorphic(e->type)) {
 			if (e->kind == Entity_Procedure && e->Procedure.is_export) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
@@ -8409,6 +8444,16 @@ void ir_gen_tree(irGen *s) {
 				name = ir_mangle_name(s, e);
 			}
 		}
+	#else
+			if (e->kind == Entity_Procedure && e->Procedure.is_export) {
+				// Okay
+			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
+				// Handle later
+			} else {
+				name = ir_mangle_name(s, e);
+			}
+	#endif
+
 		ir_add_entity_name(m, e, name);
 
 		switch (e->kind) {

+ 16 - 0
src/parser.cpp

@@ -3886,6 +3886,7 @@ void destroy_ast_file(AstFile *f) {
 bool init_parser(Parser *p) {
 	GB_ASSERT(p != nullptr);
 	map_init(&p->imported_files, heap_allocator());
+	map_init(&p->package_map, heap_allocator());
 	array_init(&p->packages, heap_allocator());
 	array_init(&p->imports, heap_allocator());
 	gb_mutex_init(&p->file_add_mutex);
@@ -3911,6 +3912,7 @@ void destroy_parser(Parser *p) {
 	array_free(&p->packages);
 	array_free(&p->imports);
 	map_destroy(&p->imported_files);
+	map_destroy(&p->package_map);
 	gb_mutex_destroy(&p->file_add_mutex);
 	gb_mutex_destroy(&p->file_decl_mutex);
 }
@@ -4234,6 +4236,20 @@ skip:
 void parser_add_package(Parser *p, AstPackage *package) {
 	package->id = p->packages.count+1;
 	array_add(&p->packages, package);
+	if (package->name.len > 0) {
+		HashKey key = hash_string(package->name);
+		auto found = map_get(&p->package_map, key);
+		if (found) {
+			GB_ASSERT(package->files.count > 0);
+			AstFile *f = package->files[0];
+			error(f->package_token, "Non-unique package name '%.*s'", LIT(package->name));
+			GB_ASSERT((*found)->files.count > 0);
+			TokenPos pos = (*found)->files[0]->package_token.pos;
+			gb_printf_err("\tpreviously declared at %.*s(%td:%td)", LIT(pos.file), pos.line, pos.column);
+		} else {
+			map_set(&p->package_map, key, package);
+		}
+	}
 }
 
 ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {

+ 1 - 0
src/parser.hpp

@@ -99,6 +99,7 @@ struct AstPackage {
 struct Parser {
 	String                 init_fullpath;
 	Map<bool>              imported_files; // Key: String (fullpath)
+	Map<AstPackage *>      package_map; // Key: String (package name)
 	Array<AstPackage *>    packages;
 	Array<ImportedPackage> imports;
 	isize                  total_token_count;

+ 7 - 5
src/unicode.cpp

@@ -9,9 +9,11 @@ extern "C" {
 
 
 bool rune_is_letter(Rune r) {
-	if ((r < 0x80 && gb_char_is_alpha(cast(char)r)) ||
-	    r == '_') {
-		return true;
+	if (r < 0x80) {
+		if (r == '_') {
+			return true;
+		}
+		return gb_char_is_alpha(cast(char)r) != 0;
 	}
 	switch (utf8proc_category(r)) {
 	case UTF8PROC_CATEGORY_LU:
@@ -25,8 +27,8 @@ bool rune_is_letter(Rune r) {
 }
 
 bool rune_is_digit(Rune r) {
-	if (r < 0x80 && gb_is_between(r, '0', '9')) {
-		return true;
+	if (r < 0x80) {
+		return gb_is_between(r, '0', '9');
 	}
 	return utf8proc_category(r) == UTF8PROC_CATEGORY_ND;
 }