From 17204bd1c23934c878c699e026aa8994e430a372 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 28 Sep 2025 20:40:26 +0100 Subject: Global const unions with `@(rodata)` --- src/llvm_backend.cpp | 75 +++++++++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 33 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 3af473c3a..8ac68d9bf 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3262,36 +3262,13 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { lbModule *m = &gen->default_module; String name = lb_get_entity_name(m, e); + lbGlobalVariable var = {}; + var.decl = decl; + lbValue g = {}; - g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name)); g.type = alloc_type_pointer(e->type); + g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name)); - 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; if (decl->init_expr != nullptr) { TypeAndValue tav = type_and_value_of_expr(decl->init_expr); @@ -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 (!var.is_initialized) { + 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) { -- cgit v1.2.3 From 17c9e1d76b3ff4a3cb2edb3dc0b6b070adaef91e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 28 Sep 2025 22:11:46 +0100 Subject: Fix global initialization when non was set --- src/llvm_backend.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8ac68d9bf..873f67cde 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -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; @@ -3269,7 +3270,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { 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)) { @@ -3313,7 +3313,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass); LLVMSetExternallyInitialized(g.value, true); lb_add_foreign_library_path(m, e->Variable.foreign_library); - } else if (!var.is_initialized) { + } else if (LLVMGetInitializer(g.value) == nullptr) { LLVMSetInitializer(g.value, LLVMConstNull(lb_type(m, e->type))); } if (is_export) { -- cgit v1.2.3 From 4877214f34abbccb8d7b11d773371fa935fe73d3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 28 Sep 2025 23:53:07 +0100 Subject: Add more `check_is_operand_compound_lit_constant` uses --- src/check_expr.cpp | 20 ++++++++++++++++---- src/llvm_backend.cpp | 10 ++++++++-- src/types.cpp | 5 ++++- 3 files changed, 28 insertions(+), 7 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index a59dbdc42..10fec1890 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8686,8 +8686,12 @@ gb_internal bool check_is_operand_compound_lit_constant(CheckerContext *c, Opera } } if (field_type != nullptr && is_type_typeid(field_type) && o->mode == Addressing_Type) { + add_type_info_type(c, o->type); return true; } + if (is_type_any(field_type)) { + return false; + } return o->mode == Addressing_Constant; } @@ -10052,7 +10056,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, fv->value, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } } else { Operand op_index = {}; check_expr(c, &op_index, fv->field); @@ -10289,7 +10295,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, fv->value, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } TokenKind upper_op = Token_LtEq; if (op.kind == Token_RangeHalf) { @@ -10330,7 +10338,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, fv->value, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } add_to_seen_map(c, &seen, op_index); } @@ -10360,7 +10370,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * check_expr_with_type_hint(c, &operand, e, elem_type); check_assignment(c, &operand, elem_type, context_name); - is_constant = is_constant && operand.mode == Addressing_Constant; + if (is_constant) { + is_constant = check_is_operand_compound_lit_constant(c, &operand, elem_type); + } } if (max < index) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 873f67cde..6a15e11a6 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) { @@ -3272,7 +3272,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { 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; @@ -3287,6 +3287,12 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { g.value = nullptr; g.value = LLVMAddGlobal(m->mod, LLVMTypeOf(init.value), alloc_cstring(permanent_allocator(), name)); + if (e->token.string == "node_camera_info") { + gb_printf_err("HERE!\n"); + gb_printf_err("%s\n", LLVMPrintValueToString(init.value)); + } + + LLVMSetInitializer(g.value, init.value); var.is_initialized = true; if (cc.is_rodata) { diff --git a/src/types.cpp b/src/types.cpp index 814f99eff..62e47259d 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2536,7 +2536,10 @@ gb_internal bool elem_type_can_be_constant(Type *t) { if (t == t_invalid) { return false; } - if (is_type_any(t) || is_type_raw_union(t)) { + if (is_type_any(t)) { + return false; + } + if (is_type_raw_union(t)) { return false; } if (is_type_union(t)) { -- cgit v1.2.3 From 4f442c60453df9e421dad8314fb76231d8bed344 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 29 Sep 2025 09:51:23 +0100 Subject: Rearrange const union initialization so that it is priority --- src/llvm_backend.cpp | 6 -- src/llvm_backend_const.cpp | 145 +++++++++++---------------------------------- 2 files changed, 35 insertions(+), 116 deletions(-) (limited to 'src/llvm_backend.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 6a15e11a6..ec9630a47 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3287,12 +3287,6 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { g.value = nullptr; g.value = LLVMAddGlobal(m->mod, LLVMTypeOf(init.value), alloc_cstring(permanent_allocator(), name)); - if (e->token.string == "node_camera_info") { - gb_printf_err("HERE!\n"); - gb_printf_err("%s\n", LLVMPrintValueToString(init.value)); - } - - LLVMSetInitializer(g.value, init.value); var.is_initialized = true; if (cc.is_rodata) { diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index cde610cc8..d27b2012b 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -549,101 +549,6 @@ gb_internal bool lb_is_nested_possibly_constant(Type *ft, Selection const &sel, return lb_is_elem_const(elem, ft); } -gb_internal Slice lb_construct_const_union_flatten_values(lbModule *m, LLVMValueRef variant_value, Type *variant_type, LLVMTypeRef elem) { - LLVMTypeRef llvm_variant_type = lb_type(m, variant_type); - LLVMTypeKind variant_kind = LLVMGetTypeKind(llvm_variant_type); - LLVMTypeKind elem_kind = LLVMGetTypeKind(elem); - - if (is_type_struct(variant_type)) { - Type *st = base_type(variant_type); - GB_ASSERT(st->kind == Type_Struct); - if (st->Struct.fields.count == 1) { - LLVMValueRef f = llvm_const_extract_value(m, variant_value, 0); - return lb_construct_const_union_flatten_values(m, f, st->Struct.fields[0]->type, elem); - } - } else if (is_llvm_type_slice_like(llvm_variant_type)) { - if (lb_sizeof(elem) == build_context.ptr_size) { - LLVMValueRef *elems = temporary_alloc_array(2); - elems[0] = llvm_const_extract_value(m, variant_value, 0); - elems[0] = LLVMConstPtrToInt(elems[0], elem); - - elems[1] = llvm_const_extract_value(m, variant_value, 1); - - return {elems, 2}; - } - } else if (is_type_array_like(variant_type)) { - Type *array_elem = base_array_type(variant_type); - isize array_count = get_array_type_count(variant_type); - Slice array = temporary_slice_make(array_count); - for (isize i = 0; i < array_count; i++) { - LLVMValueRef v = llvm_const_extract_value(m, variant_value, 0); - auto res = lb_construct_const_union_flatten_values(m, v, array_elem, elem); - if (res.count != 1) { - return {}; - } - array[i] = res[0]; - } - return array; - } else if (variant_kind == LLVMIntegerTypeKind) { - if (elem == llvm_variant_type) { - LLVMValueRef *elems = temporary_alloc_array(1); - elems[0] = variant_value; - return {elems, 1}; - } else if (!is_type_different_to_arch_endianness(variant_type)) { - i64 elem_size = lb_sizeof(elem); - i64 variant_size = lb_sizeof(llvm_variant_type); - if (elem_size > variant_size) { - u64 val = LLVMConstIntGetZExtValue(variant_value); - - LLVMValueRef *elems = temporary_alloc_array(1); - elems[0] = LLVMConstInt(elem, val, false); - return {elems, 1}; - } - } - } else if (!is_type_different_to_arch_endianness(variant_type) && - elem_kind == LLVMIntegerTypeKind) { - switch (variant_kind) { - case LLVMHalfTypeKind: - { - LLVMBool loses = false; - f64 res = LLVMConstRealGetDouble(variant_value, &loses); - u16 val = f32_to_f16(cast(f32)res); - - LLVMValueRef *elems = temporary_alloc_array(1); - elems[0] = LLVMConstInt(elem, val, false); - return {elems, 1}; - } - break; - case LLVMFloatTypeKind: - { - LLVMBool loses = false; - f64 res = LLVMConstRealGetDouble(variant_value, &loses); - union { f32 f; u32 i; } val = {}; - val.f = cast(f32)res; - - LLVMValueRef *elems = temporary_alloc_array(1); - elems[0] = LLVMConstInt(elem, val.i, false); - return {elems, 1}; - } - break; - case LLVMDoubleTypeKind: - { - LLVMBool loses = false; - f64 res = LLVMConstRealGetDouble(variant_value, &loses); - union { f64 f; u64 i; } val = {}; - val.f = res; - - LLVMValueRef *elems = temporary_alloc_array(1); - elems[0] = LLVMConstInt(elem, val.i, false); - return {elems, 1}; - } - break; - } - } - - return {}; -} - gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lbConstContext cc, Type *value_type) { if (cc.allow_local) { cc.is_rodata = false; @@ -659,21 +564,6 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb type = core_type(type); value = convert_exact_value_for_type(value, type); - if (value.kind == ExactValue_Typeid) { - return lb_typeid(m, value.value_typeid); - } - - if (value.kind == ExactValue_Invalid) { - return lb_const_nil(m, original_type); - } - - if (value.kind == ExactValue_Compound) { - ast_node(cl, CompoundLit, value.value_compound); - if (cl->elems.count == 0) { - return lb_const_nil(m, original_type); - } - } - bool is_local = cc.allow_local && m->curr_procedure != nullptr; if (is_type_union(type) && is_type_union_constantable(type)) { @@ -718,6 +608,15 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb i64 block_size = bt->Union.variant_block_size; if (are_types_identical(value_type, original_type)) { + if (value.kind == ExactValue_Compound) { + ast_node(cl, CompoundLit, value.value_compound); + if (cl->elems.count == 0) { + return lb_const_nil(m, original_type); + } + } else if (value.kind == ExactValue_Invalid) { + return lb_const_nil(m, original_type); + } + GB_PANIC("%s vs %s", type_to_string(value_type), type_to_string(original_type)); } @@ -774,6 +673,24 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb return res; } + // NOTE(bill): This has to be done AFTER the union stuff + if (value.kind == ExactValue_Invalid) { + return lb_const_nil(m, original_type); + } + + + if (value.kind == ExactValue_Typeid) { + return lb_typeid(m, value.value_typeid); + } + + if (value.kind == ExactValue_Compound) { + ast_node(cl, CompoundLit, value.value_compound); + if (cl->elems.count == 0) { + return lb_const_nil(m, original_type); + } + } + + // GB_ASSERT_MSG(is_type_typed(type), "%s", type_to_string(type)); if (is_type_slice(type)) { @@ -1586,6 +1503,14 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb if (elem_type_can_be_constant(f->type)) { if (sel.index.count == 1) { lbValue value = lb_const_value(m, f->type, tav.value, cc, tav.type); + if (is_type_union(f->type)) { + if (f->token.string == "default_value") { + if (LLVMIsNull(value.value)) { + gb_printf_err("HERE: %s %s\n", type_to_string(f->type), LLVMPrintValueToString(value.value)); + GB_PANIC("GAH"); + } + } + } LLVMTypeRef value_type = LLVMTypeOf(value.value); GB_ASSERT_MSG(lb_sizeof(value_type) == type_size_of(f->type), "%s vs %s", LLVMPrintTypeToString(value_type), type_to_string(f->type)); values[index] = value.value; -- cgit v1.2.3