Separate ini global var stuff

This commit is contained in:
gingerBill
2025-09-19 13:52:25 +01:00
parent a8b2b1a23b
commit ec91e2c15b
+76 -63
View File
@@ -1924,6 +1924,74 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) {
return 0;
}
gb_internal bool lb_init_global_var(lbModule *m, lbProcedure *p, Entity *e, Ast *init_expr, lbGlobalVariable &var) {
if (init_expr != nullptr) {
lbValue init = lb_build_expr(p, init_expr);
if (init.value == nullptr) {
LLVMTypeRef global_type = llvm_addr_type(p->module, var.var);
if (is_type_untyped_nil(init.type)) {
LLVMSetInitializer(var.var.value, LLVMConstNull(global_type));
var.is_initialized = true;
if (e->Variable.is_rodata) {
LLVMSetGlobalConstant(var.var.value, true);
}
return true;
}
GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr));
}
if (is_type_any(e->type) || is_type_union(e->type)) {
var.init = init;
} else if (lb_is_const_or_global(init)) {
if (!var.is_initialized) {
if (is_type_proc(init.type)) {
init.value = LLVMConstPointerCast(init.value, lb_type(p->module, init.type));
}
LLVMSetInitializer(var.var.value, init.value);
var.is_initialized = true;
if (e->Variable.is_rodata) {
LLVMSetGlobalConstant(var.var.value, true);
}
return true;
}
} else {
var.init = init;
}
}
if (var.init.value != nullptr) {
GB_ASSERT(!var.is_initialized);
Type *t = type_deref(var.var.type);
if (is_type_any(t)) {
// NOTE(bill): Edge case for 'any' type
Type *var_type = default_type(var.init.type);
gbString var_name = gb_string_make(permanent_allocator(), "__$global_any::");
gbString e_str = string_canonical_entity_name(temporary_allocator(), e);
var_name = gb_string_append_length(var_name, e_str, gb_strlen(e_str));
lbAddr g = lb_add_global_generated_with_name(m, var_type, {}, make_string_c(var_name));
lb_addr_store(p, g, var.init);
lbValue gp = lb_addr_get_ptr(p, g);
lbValue data = lb_emit_struct_ep(p, var.var, 0);
lbValue ti = lb_emit_struct_ep(p, var.var, 1);
lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr));
lb_emit_store(p, ti, lb_typeid(p->module, var_type));
} else {
LLVMTypeRef vt = llvm_addr_type(p->module, var.var);
lbValue src0 = lb_emit_conv(p, var.init, t);
LLVMValueRef src = OdinLLVMBuildTransmute(p, src0.value, vt);
LLVMValueRef dst = var.var.value;
LLVMBuildStore(p->builder, src, dst);
}
var.is_initialized = true;
}
return false;
}
gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedure *p) {
lb_begin_procedure_body(p);
@@ -1944,73 +2012,13 @@ gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedur
Entity *e = var.decl->entity;
GB_ASSERT(e->kind == Entity_Variable);
e->code_gen_module = entity_module;
Ast *init_expr = var.decl->init_expr;
if (init_expr != nullptr) {
lbValue init = lb_build_expr(p, init_expr);
if (init.value == nullptr) {
LLVMTypeRef global_type = llvm_addr_type(p->module, var.var);
if (is_type_untyped_nil(init.type)) {
LLVMSetInitializer(var.var.value, LLVMConstNull(global_type));
var.is_initialized = true;
if (e->Variable.is_rodata) {
LLVMSetGlobalConstant(var.var.value, true);
}
continue;
}
GB_PANIC("Invalid init value, got %s", expr_to_string(init_expr));
}
if (is_type_any(e->type) || is_type_union(e->type)) {
var.init = init;
} else if (lb_is_const_or_global(init)) {
if (!var.is_initialized) {
if (is_type_proc(init.type)) {
init.value = LLVMConstPointerCast(init.value, lb_type(p->module, init.type));
}
LLVMSetInitializer(var.var.value, init.value);
var.is_initialized = true;
if (e->Variable.is_rodata) {
LLVMSetGlobalConstant(var.var.value, true);
}
continue;
}
} else {
var.init = init;
}
}
if (var.init.value != nullptr) {
GB_ASSERT(!var.is_initialized);
Type *t = type_deref(var.var.type);
if (is_type_any(t)) {
// NOTE(bill): Edge case for 'any' type
Type *var_type = default_type(var.init.type);
gbString var_name = gb_string_make(permanent_allocator(), "__$global_any::");
gbString e_str = string_canonical_entity_name(temporary_allocator(), e);
var_name = gb_string_append_length(var_name, e_str, gb_strlen(e_str));
lbAddr g = lb_add_global_generated_with_name(m, var_type, {}, make_string_c(var_name));
lb_addr_store(p, g, var.init);
lbValue gp = lb_addr_get_ptr(p, g);
lbValue data = lb_emit_struct_ep(p, var.var, 0);
lbValue ti = lb_emit_struct_ep(p, var.var, 1);
lb_emit_store(p, data, lb_emit_conv(p, gp, t_rawptr));
lb_emit_store(p, ti, lb_typeid(p->module, var_type));
} else {
LLVMTypeRef vt = llvm_addr_type(p->module, var.var);
lbValue src0 = lb_emit_conv(p, var.init, t);
LLVMValueRef src = OdinLLVMBuildTransmute(p, src0.value, vt);
LLVMValueRef dst = var.var.value;
LLVMBuildStore(p->builder, src, dst);
}
var.is_initialized = true;
if (init_expr == nullptr && var.init.value == nullptr) {
continue;
}
lb_init_global_var(m, p, e, init_expr, var);
}
CheckerInfo *info = m->gen->info;
@@ -2448,7 +2456,12 @@ gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc
for (isize i = 0; i < m->missing_procedures_to_check.count; i++) {
lbProcedure *p = m->missing_procedures_to_check[i];
debugf("Generate missing procedure: %.*s module %p\n", LIT(p->name), m);
isize count = m->procedures_to_generate.count;
lb_generate_procedure(m, p);
isize new_count = m->procedures_to_generate.count;
if (count != new_count) {
gb_printf_err("NEW STUFF!\n");
}
}
return 0;
}