From 547a2831c7d7b66f823947e75c18c40329510b5a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 27 May 2018 22:09:11 +0100 Subject: [PATCH] Clean up name mangling by using unique package names per project --- core/mem/alloc.odin | 2 +- core/mem/mem.odin | 43 +++++++++++++++++++++--- core/runtime/core.odin | 15 ++++----- core/runtime/internal.odin | 47 -------------------------- src/checker.cpp | 23 ++++++------- src/checker.hpp | 3 +- src/ir.cpp | 67 +++++++++++++++++++++++++++++++------- src/parser.cpp | 16 +++++++++ src/parser.hpp | 1 + src/unicode.cpp | 12 ++++--- 10 files changed, 141 insertions(+), 88 deletions(-) diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index aef740fb1..232d56ba5 100644 --- a/core/mem/alloc.odin +++ b/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; } diff --git a/core/mem/mem.odin b/core/mem/mem.odin index 66c47bd51..15b3ff068 100644 --- a/core/mem/mem.odin +++ b/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))); diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 1346d49d1..87839538a 100644 --- a/core/runtime/core.odin +++ b/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; diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 47f56997c..8104a72ef 100644 --- a/core/runtime/internal.odin +++ b/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") diff --git a/src/checker.cpp b/src/checker.cpp index b4fab10bc..0b9323eb4 100644 --- a/src/checker.cpp +++ b/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 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; } } diff --git a/src/checker.hpp b/src/checker.hpp index 079a8acac..705f32116 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -313,6 +313,8 @@ struct CheckerInfo { Array type_info_types; Map type_info_map; // Key: Type * + + AstPackage * runtime_package; Scope * init_scope; Entity * entry_point; PtrSet minimum_dependency_set; @@ -326,7 +328,6 @@ struct Checker { AstFile * curr_ast_file; - AstPackage * runtime_package; // NOTE(bill): Procedures to check Array procs; Map package_scopes; // Key: String (fullpath) diff --git a/src/ir.cpp b/src/ir.cpp index 0afc0f8f1..9b9d6d3bf 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1575,8 +1575,9 @@ void ir_emit_zero_init(irProcedure *p, irValue *address, AstNode *expr) { auto args = array_make(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 args) { irValue *ir_emit_global_call(irProcedure *proc, char const *name_, Array 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) { diff --git a/src/parser.cpp b/src/parser.cpp index ebdeeba65..61aac5a97 100644 --- a/src/parser.cpp +++ b/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) { diff --git a/src/parser.hpp b/src/parser.hpp index a2c10c81a..ce0eed350 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -99,6 +99,7 @@ struct AstPackage { struct Parser { String init_fullpath; Map imported_files; // Key: String (fullpath) + Map package_map; // Key: String (package name) Array packages; Array imports; isize total_token_count; diff --git a/src/unicode.cpp b/src/unicode.cpp index 538e6adce..78c94e84e 100644 --- a/src/unicode.cpp +++ b/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; }