aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2025-09-29 13:12:07 +0100
committerGitHub <noreply@github.com>2025-09-29 13:12:07 +0100
commit11dc6680d2101a76e5fff8baedd8717501b625c0 (patch)
treecc80ffec2742974e4e4882eb209e03248410adbe /src/llvm_backend.cpp
parentd3b877031838c5a13c4adbfdd1d8fb77c35c9801 (diff)
parent240b2f1819294cc59b48f88ef3344bf77265fec6 (diff)
Merge pull request #5723 from odin-lang/bill/const-union
Basic support for constant union literals
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp81
1 files changed, 45 insertions, 36 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 3af473c3a..ec9630a47 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -1947,7 +1947,7 @@ gb_internal bool lb_init_global_var(lbModule *m, lbProcedure *p, Entity *e, Ast
GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr));
}
- if (is_type_any(e->type) || is_type_union(e->type)) {
+ if (is_type_any(e->type)) {
var.init = init;
} else if (lb_is_const_or_global(init)) {
if (!var.is_initialized) {
@@ -3255,6 +3255,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
}
GB_ASSERT(e->kind == Entity_Variable);
+
bool is_foreign = e->Variable.is_foreign;
bool is_export = e->Variable.is_export;
@@ -3262,40 +3263,16 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
lbModule *m = &gen->default_module;
String name = lb_get_entity_name(m, e);
- lbValue g = {};
- g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
- g.type = alloc_type_pointer(e->type);
-
- lb_apply_thread_local_model(g.value, e->Variable.thread_local_model);
-
- if (is_foreign) {
- LLVMSetLinkage(g.value, LLVMExternalLinkage);
- LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass);
- LLVMSetExternallyInitialized(g.value, true);
- lb_add_foreign_library_path(m, e->Variable.foreign_library);
- } else {
- LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type)));
- }
- if (is_export) {
- LLVMSetLinkage(g.value, LLVMDLLExportLinkage);
- LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass);
- } else if (!is_foreign) {
- LLVMSetLinkage(g.value, USE_SEPARATE_MODULES ? LLVMWeakAnyLinkage : LLVMInternalLinkage);
- }
- lb_set_linkage_from_entity_flags(m, g.value, e->flags);
- LLVMSetAlignment(g.value, cast(u32)type_align_of(e->type));
-
- if (e->Variable.link_section.len > 0) {
- LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section));
- }
-
lbGlobalVariable var = {};
- var.var = g;
var.decl = decl;
+ lbValue g = {};
+ g.type = alloc_type_pointer(e->type);
+ g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
+
if (decl->init_expr != nullptr) {
TypeAndValue tav = type_and_value_of_expr(decl->init_expr);
- if (!is_type_any(e->type) && !is_type_union(e->type)) {
+ if (!is_type_any(e->type)) {
if (tav.mode != Addressing_Invalid) {
if (tav.value.kind != ExactValue_Invalid) {
auto cc = LB_CONST_CONTEXT_DEFAULT;
@@ -3305,6 +3282,11 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
ExactValue v = tav.value;
lbValue init = lb_const_value(m, tav.type, v, cc);
+
+ LLVMDeleteGlobal(g.value);
+ g.value = nullptr;
+ g.value = LLVMAddGlobal(m->mod, LLVMTypeOf(init.value), alloc_cstring(permanent_allocator(), name));
+
LLVMSetInitializer(g.value, init.value);
var.is_initialized = true;
if (cc.is_rodata) {
@@ -3323,15 +3305,32 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
LLVMSetGlobalConstant(g.value, true);
}
- if (e->flags & EntityFlag_Require) {
- lb_append_to_compiler_used(m, g.value);
- }
- array_add(&global_variables, var);
+ lb_apply_thread_local_model(g.value, e->Variable.thread_local_model);
- lb_add_entity(m, e, g);
- lb_add_member(m, name, g);
+ if (is_foreign) {
+ LLVMSetLinkage(g.value, LLVMExternalLinkage);
+ LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass);
+ LLVMSetExternallyInitialized(g.value, true);
+ lb_add_foreign_library_path(m, e->Variable.foreign_library);
+ } else if (LLVMGetInitializer(g.value) == nullptr) {
+ LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type)));
+ }
+ if (is_export) {
+ LLVMSetLinkage(g.value, LLVMDLLExportLinkage);
+ LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass);
+ } else if (!is_foreign) {
+ LLVMSetLinkage(g.value, USE_SEPARATE_MODULES ? LLVMWeakAnyLinkage : LLVMInternalLinkage);
+ }
+ lb_set_linkage_from_entity_flags(m, g.value, e->flags);
+ LLVMSetAlignment(g.value, cast(u32)type_align_of(e->type));
+ if (e->Variable.link_section.len > 0) {
+ LLVMSetSection(g.value, alloc_cstring(permanent_allocator(), e->Variable.link_section));
+ }
+ if (e->flags & EntityFlag_Require) {
+ lb_append_to_compiler_used(m, g.value);
+ }
if (m->debug_builder) {
String global_name = e->token.string;
@@ -3361,6 +3360,16 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
LLVMGlobalSetMetadata(g.value, 0, global_variable_metadata);
}
}
+
+ g.value = LLVMConstPointerCast(g.value, lb_type(m, alloc_type_pointer(e->type)));
+
+ var.var = g;
+ array_add(&global_variables, var);
+
+ lb_add_entity(m, e, g);
+ lb_add_member(m, name, g);
+
+
}
if (build_context.ODIN_DEBUG) {