diff options
Diffstat (limited to 'src/llvm_backend_general.cpp')
| -rw-r--r-- | src/llvm_backend_general.cpp | 307 |
1 files changed, 110 insertions, 197 deletions
diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 9dc603993..0705e2e93 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -15,13 +15,18 @@ gb_global isize lb_global_type_info_member_offsets_index = 0; gb_global isize lb_global_type_info_member_usings_index = 0; gb_global isize lb_global_type_info_member_tags_index = 0; - gb_internal void lb_init_module(lbModule *m, Checker *c) { m->info = &c->info; gbString module_name = gb_string_make(heap_allocator(), "odin_package"); if (m->file) { - module_name = gb_string_append_fmt(module_name, "-%u", m->file->id+1); + if (m->pkg) { + module_name = gb_string_appendc(module_name, "-"); + module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len); + } + module_name = gb_string_appendc(module_name, "-"); + String filename = filename_from_path(m->file->filename); + module_name = gb_string_append_length(module_name, filename.text, filename.len); } else if (m->pkg) { module_name = gb_string_appendc(module_name, "-"); module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len); @@ -68,10 +73,7 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { string_map_init(&m->procedures); string_map_init(&m->const_strings); map_init(&m->function_type_map); - map_init(&m->equal_procs); - map_init(&m->hasher_procs); - map_init(&m->map_get_procs); - map_init(&m->map_set_procs); + string_map_init(&m->gen_procs); if (USE_SEPARATE_MODULES) { array_init(&m->procedures_to_generate, a, 0, 1<<10); map_init(&m->procedure_values, 1<<11); @@ -219,7 +221,7 @@ gb_internal void lb_loop_end(lbProcedure *p, lbLoopData const &data) { gb_internal void lb_make_global_private_const(LLVMValueRef global_data) { LLVMSetLinkage(global_data, LLVMLinkerPrivateLinkage); - LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr); + // LLVMSetUnnamedAddress(global_data, LLVMGlobalUnnamedAddr); LLVMSetGlobalConstant(global_data, true); } gb_internal void lb_make_global_private_const(lbAddr const &addr) { @@ -540,6 +542,22 @@ gb_internal lbValue lb_build_addr_ptr(lbProcedure *p, Ast *expr) { return lb_addr_get_ptr(p, addr); } +gb_internal void lb_set_file_line_col(lbProcedure *p, Array<lbValue> arr, TokenPos pos) { + String file = get_file_path_string(pos.file_id); + i32 line = pos.line; + i32 col = pos.column; + + if (build_context.obfuscate_source_code_locations) { + file = obfuscate_string(file, "F"); + line = obfuscate_i32(line); + col = obfuscate_i32(col); + } + + arr[0] = lb_find_or_add_entity_string(p->module, file); + arr[1] = lb_const_int(p->module, t_i32, line); + arr[2] = lb_const_int(p->module, t_i32, col); +} + gb_internal void lb_emit_bounds_check(lbProcedure *p, Token token, lbValue index, lbValue len) { if (build_context.no_bounds_check) { return; @@ -553,14 +571,8 @@ gb_internal void lb_emit_bounds_check(lbProcedure *p, Token token, lbValue index index = lb_emit_conv(p, index, t_int); len = lb_emit_conv(p, len, t_int); - lbValue file = lb_find_or_add_entity_string(p->module, get_file_path_string(token.pos.file_id)); - lbValue line = lb_const_int(p->module, t_i32, token.pos.line); - lbValue column = lb_const_int(p->module, t_i32, token.pos.column); - auto args = array_make<lbValue>(temporary_allocator(), 5); - args[0] = file; - args[1] = line; - args[2] = column; + lb_set_file_line_col(p, args, token.pos); args[3] = index; args[4] = len; @@ -582,14 +594,8 @@ gb_internal void lb_emit_matrix_bounds_check(lbProcedure *p, Token token, lbValu row_count = lb_emit_conv(p, row_count, t_int); column_count = lb_emit_conv(p, column_count, t_int); - lbValue file = lb_find_or_add_entity_string(p->module, get_file_path_string(token.pos.file_id)); - lbValue line = lb_const_int(p->module, t_i32, token.pos.line); - lbValue column = lb_const_int(p->module, t_i32, token.pos.column); - auto args = array_make<lbValue>(temporary_allocator(), 7); - args[0] = file; - args[1] = line; - args[2] = column; + lb_set_file_line_col(p, args, token.pos); args[3] = row_index; args[4] = column_index; args[5] = row_count; @@ -610,14 +616,8 @@ gb_internal void lb_emit_multi_pointer_slice_bounds_check(lbProcedure *p, Token low = lb_emit_conv(p, low, t_int); high = lb_emit_conv(p, high, t_int); - lbValue file = lb_find_or_add_entity_string(p->module, get_file_path_string(token.pos.file_id)); - lbValue line = lb_const_int(p->module, t_i32, token.pos.line); - lbValue column = lb_const_int(p->module, t_i32, token.pos.column); - auto args = array_make<lbValue>(permanent_allocator(), 5); - args[0] = file; - args[1] = line; - args[2] = column; + lb_set_file_line_col(p, args, token.pos); args[3] = low; args[4] = high; @@ -632,16 +632,11 @@ gb_internal void lb_emit_slice_bounds_check(lbProcedure *p, Token token, lbValue return; } - lbValue file = lb_find_or_add_entity_string(p->module, get_file_path_string(token.pos.file_id)); - lbValue line = lb_const_int(p->module, t_i32, token.pos.line); - lbValue column = lb_const_int(p->module, t_i32, token.pos.column); high = lb_emit_conv(p, high, t_int); if (!lower_value_used) { auto args = array_make<lbValue>(permanent_allocator(), 5); - args[0] = file; - args[1] = line; - args[2] = column; + lb_set_file_line_col(p, args, token.pos); args[3] = high; args[4] = len; @@ -651,9 +646,7 @@ gb_internal void lb_emit_slice_bounds_check(lbProcedure *p, Token token, lbValue low = lb_emit_conv(p, low, t_int); auto args = array_make<lbValue>(permanent_allocator(), 6); - args[0] = file; - args[1] = line; - args[2] = column; + lb_set_file_line_col(p, args, token.pos); args[3] = low; args[4] = high; args[5] = len; @@ -734,6 +727,17 @@ gb_internal LLVMValueRef OdinLLVMBuildLoad(lbProcedure *p, LLVMTypeRef type, LLV if (is_packed != 0) { LLVMSetAlignment(result, 1); } + u64 align = LLVMGetAlignment(result); + u64 align_min = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MIN_ALIGN); + u64 align_max = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MAX_ALIGN); + if (align_min != 0 && align < align_min) { + align = align_min; + } + if (align_max != 0 && align > align_max) { + align = align_max; + } + GB_ASSERT(align <= UINT_MAX); + LLVMSetAlignment(result, (unsigned int)align); } return result; @@ -1009,7 +1013,7 @@ gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) { LLVMConstInt(LLVMInt64TypeInContext(p->module->ctx), lb_sizeof(LLVMTypeOf(value.value)), false)); return; } else if (LLVMIsConstant(value.value)) { - lbAddr addr = lb_add_global_generated(p->module, value.type, value, nullptr); + lbAddr addr = lb_add_global_generated_from_procedure(p, value.type, value); lb_make_global_private_const(addr); LLVMValueRef dst_ptr = ptr.value; @@ -1442,148 +1446,30 @@ 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) { - 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; -} - -gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedure *p, lbModule *module) { - // 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; - 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; - return name; - } -} - -gb_internal String lb_get_entity_name(lbModule *m, Entity *e, String default_name) { +gb_internal String lb_get_entity_name(lbModule *m, Entity *e) { GB_ASSERT(m != nullptr); - if (e != nullptr && e->kind == Entity_TypeName && e->TypeName.ir_mangled_name.len != 0) { + GB_ASSERT(e != nullptr); + if (e->kind == Entity_TypeName && e->TypeName.ir_mangled_name.len != 0) { return e->TypeName.ir_mangled_name; + } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len != 0) { + return e->Procedure.link_name; } - GB_ASSERT(e != nullptr); if (e->pkg == nullptr) { return e->token.string; } - if (e->kind == Entity_TypeName && (e->scope->flags & ScopeFlag_File) == 0) { - return lb_set_nested_type_name_ir_mangled_name(e, nullptr, m); - } + gbString w = string_canonical_entity_name(heap_allocator(), e); + defer (gb_string_free(w)); - 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); - } - if (name.len == 0) { - name = e->token.string; - } + String name = copy_string(permanent_allocator(), make_string(cast(u8 const *)w, gb_string_length(w))); 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; @@ -1901,15 +1787,24 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return type; } type = LLVMStructCreateNamed(ctx, name); - LLVMTypeRef fields[2] = { - lb_type(m, t_rawptr), - lb_type(m, t_typeid), - }; - LLVMStructSetBody(type, fields, 2, false); + if (build_context.ptr_size == 4) { + LLVMTypeRef fields[3] = { + lb_type(m, t_rawptr), + lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size), // padding + lb_type(m, t_typeid), + }; + LLVMStructSetBody(type, fields, 3, false); + } else { + LLVMTypeRef fields[2] = { + lb_type(m, t_rawptr), + lb_type(m, t_typeid), + }; + LLVMStructSetBody(type, fields, 2, false); + } return type; } - case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 8*cast(unsigned)build_context.ptr_size); + case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 64); // Endian Specific Types case Basic_i16le: return LLVMInt16TypeInContext(ctx); @@ -2121,6 +2016,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { } i64 prev_offset = 0; + bool requires_packing = type->Struct.is_packed; for (i32 field_index : struct_fields_index_by_increasing_offset(temporary_allocator(), type)) { Entity *field = type->Struct.fields[field_index]; i64 offset = type->Struct.offsets[field_index]; @@ -2141,6 +2037,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { field_type = t_rawptr; } + // max_field_align might misalign items in a way that requires packing + // so check the alignment of all fields to see if packing is required. + requires_packing = requires_packing || ((offset % type_align_of(field_type)) != 0); + array_add(&fields, lb_type(m, field_type)); prev_offset = offset + type_size_of(field->type); @@ -2155,7 +2055,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { GB_ASSERT(fields[i] != nullptr); } - LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, type->Struct.is_packed); + LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing); map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping); map_set(&m->struct_field_remapping, cast(void *)type, field_remapping); #if 0 @@ -2601,7 +2501,7 @@ general_end:; GB_ASSERT(p->decl_block != p->curr_block); i64 max_align = gb_max(lb_alignof(src_type), lb_alignof(dst_type)); - max_align = gb_max(max_align, 4); + max_align = gb_max(max_align, 16); LLVMValueRef ptr = llvm_alloca(p, dst_type, max_align); @@ -2627,12 +2527,10 @@ gb_internal LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String co false); - isize max_len = 7+8+1; - char *name = gb_alloc_array(permanent_allocator(), char, max_len); - - u32 id = m->gen->global_array_index.fetch_add(1); - isize len = gb_snprintf(name, max_len, "csbs$%x", id); - len -= 1; + u32 id = m->global_array_index.fetch_add(1); + gbString name = gb_string_make(temporary_allocator(), "csbs$"); + name = gb_string_appendc(name, m->module_name); + name = gb_string_append_fmt(name, "$%x", id); LLVMTypeRef type = LLVMTypeOf(data); LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); @@ -2670,14 +2568,11 @@ gb_internal lbValue lb_find_or_add_entity_string_byte_slice_with_type(lbModule * false); - char *name = nullptr; - { - isize max_len = 7+8+1; - name = gb_alloc_array(permanent_allocator(), char, max_len); - u32 id = m->gen->global_array_index.fetch_add(1); - isize len = gb_snprintf(name, max_len, "csbs$%x", id); - len -= 1; - } + u32 id = m->global_array_index.fetch_add(1); + gbString name = gb_string_make(temporary_allocator(), "csba$"); + name = gb_string_appendc(name, m->module_name); + name = gb_string_append_fmt(name, "$%x", id); + LLVMTypeRef type = LLVMTypeOf(data); LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); LLVMSetInitializer(global_data, data); @@ -2863,6 +2758,8 @@ gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &pr pl->decl->code_gen_module = m; e->decl_info = pl->decl; pl->decl->entity = e; + e->parent_proc_decl = pl->decl->parent; + e->Procedure.is_anonymous = true; e->flags |= EntityFlag_ProcBodyChecked; lbProcedure *p = lb_create_procedure(m, e); @@ -2883,17 +2780,14 @@ gb_internal lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &pr } -gb_internal lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue value, Entity **entity_) { +gb_internal lbAddr lb_add_global_generated_with_name(lbModule *m, Type *type, lbValue value, String name, Entity **entity_) { + GB_ASSERT(name.len != 0); GB_ASSERT(type != nullptr); type = default_type(type); - isize max_len = 7+8+1; - u8 *str = cast(u8 *)gb_alloc_array(permanent_allocator(), u8, max_len); - - u32 id = m->gen->global_generated_index.fetch_add(1); - - isize len = gb_snprintf(cast(char *)str, max_len, "ggv$%x", id); - String name = make_string(str, len-1); + u8 *str = cast(u8 *)gb_alloc_array(temporary_allocator(), u8, name.len); + memcpy(str, name.text, name.len); + str[name.len] = 0; Scope *scope = nullptr; Entity *e = alloc_entity_variable(scope, make_token_ident(name), type); @@ -2915,6 +2809,25 @@ gb_internal lbAddr lb_add_global_generated(lbModule *m, Type *type, lbValue valu return lb_addr(g); } + +gb_internal lbAddr lb_add_global_generated_from_procedure(lbProcedure *p, Type *type, lbValue value) { + GB_ASSERT(type != nullptr); + type = default_type(type); + + u32 index = ++p->global_generated_index; + + gbString s = gb_string_make(temporary_allocator(), "ggv$"); + // s = gb_string_appendc(s, p->module->module_name); + // s = gb_string_appendc(s, "$"); + s = gb_string_append_length(s, p->name.text, p->name.len); + s = gb_string_append_fmt(s, "$%u", index); + + String name = make_string(cast(u8 const *)s, gb_string_length(s)); + return lb_add_global_generated_with_name(p->module, type, value, name); +} + + + 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); @@ -3022,7 +2935,7 @@ gb_internal lbValue lb_generate_global_array(lbModule *m, Type *elem_type, i64 c g.type = alloc_type_pointer(t); LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, t))); LLVMSetLinkage(g.value, LLVMPrivateLinkage); - LLVMSetUnnamedAddress(g.value, LLVMGlobalUnnamedAddr); + // LLVMSetUnnamedAddress(g.value, LLVMGlobalUnnamedAddr); string_map_set(&m->members, s, g); return g; } |