aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_general.cpp
diff options
context:
space:
mode:
authorflysand7 <thebumboni@gmail.com>2025-03-02 20:05:55 +1100
committerflysand7 <thebumboni@gmail.com>2025-03-02 20:05:55 +1100
commit698c510ba7bb5794b3eeed7aecb8327386f00da7 (patch)
tree8c376debaf24f3ac8782192310e49e730509cdf9 /src/llvm_backend_general.cpp
parent5d290dce069cb257b2e3effdd4e9b1e7dc21e722 (diff)
parentf390598b403eb336276ef9161753bf26d24d0d01 (diff)
Merge branch 'master' into docs-simd
Diffstat (limited to 'src/llvm_backend_general.cpp')
-rw-r--r--src/llvm_backend_general.cpp307
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;
}