Browse Source

fix global and static any

Fixes #4627
Laytan Laats 2 months ago
parent
commit
c35a45e823
4 changed files with 100 additions and 60 deletions
  1. 5 20
      src/llvm_backend.cpp
  2. 24 19
      src/llvm_backend_general.cpp
  3. 31 21
      src/llvm_backend_stmt.cpp
  4. 40 0
      tests/internal/test_global_any.odin

+ 5 - 20
src/llvm_backend.cpp

@@ -1973,14 +1973,14 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
 				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(main_module, var_type, var.init, make_string_c(var_name));
+				lbAddr g = lb_add_global_generated_with_name(main_module, 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_type_info(p, var_type));
+				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);
@@ -3194,24 +3194,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
 		lbValue g = {};
 		g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
 		g.type = alloc_type_pointer(e->type);
-		if (e->Variable.thread_local_model != "") {
-			LLVMSetThreadLocal(g.value, true);
-
-			String m = e->Variable.thread_local_model;
-			LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel;
-			if (m == "default") {
-				mode = LLVMGeneralDynamicTLSModel;
-			} else if (m == "localdynamic") {
-				mode = LLVMLocalDynamicTLSModel;
-			} else if (m == "initialexec") {
-				mode = LLVMInitialExecTLSModel;
-			} else if (m == "localexec") {
-				mode = LLVMLocalExecTLSModel;
-			} else {
-				GB_PANIC("Unhandled thread local mode %.*s", LIT(m));
-			}
-			LLVMSetThreadLocalMode(g.value, mode);
-		}
+
+		lb_apply_thread_local_model(g.value, e->Variable.thread_local_model);
+
 		if (is_foreign) {
 			LLVMSetLinkage(g.value, LLVMExternalLinkage);
 			LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass);

+ 24 - 19
src/llvm_backend_general.cpp

@@ -2387,6 +2387,29 @@ gb_internal void lb_add_attribute_to_proc_with_string(lbModule *m, LLVMValueRef
 }
 
 
+gb_internal bool lb_apply_thread_local_model(LLVMValueRef value, String model) {
+	if (model != "") {
+		LLVMSetThreadLocal(value, true);
+
+		LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel;
+		if (model == "default") {
+			mode = LLVMGeneralDynamicTLSModel;
+		} else if (model == "localdynamic") {
+			mode = LLVMLocalDynamicTLSModel;
+		} else if (model == "initialexec") {
+			mode = LLVMInitialExecTLSModel;
+		} else if (model == "localexec") {
+			mode = LLVMLocalExecTLSModel;
+		} else {
+			GB_PANIC("Unhandled thread local mode %.*s", LIT(model));
+		}
+		LLVMSetThreadLocalMode(value, mode);
+		return true;
+	}
+
+	return false;
+}
+
 
 gb_internal void lb_add_edge(lbBlock *from, lbBlock *to) {
 	LLVMValueRef instr = LLVMGetLastInstruction(from->block);
@@ -2990,25 +3013,7 @@ gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e) {
 
 			lb_set_entity_from_other_modules_linkage_correctly(other_module, e, name);
 
-			if (e->Variable.thread_local_model != "") {
-				LLVMSetThreadLocal(g.value, true);
-
-				String m = e->Variable.thread_local_model;
-				LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel;
-				if (m == "default") {
-					mode = LLVMGeneralDynamicTLSModel;
-				} else if (m == "localdynamic") {
-					mode = LLVMLocalDynamicTLSModel;
-				} else if (m == "initialexec") {
-					mode = LLVMInitialExecTLSModel;
-				} else if (m == "localexec") {
-					mode = LLVMLocalExecTLSModel;
-				} else {
-					GB_PANIC("Unhandled thread local mode %.*s", LIT(m));
-				}
-				LLVMSetThreadLocalMode(g.value, mode);
-			}
-
+			lb_apply_thread_local_model(g.value, e->Variable.thread_local_model);
 
 			return g;
 		}

+ 31 - 21
src/llvm_backend_stmt.cpp

@@ -2022,33 +2022,43 @@ gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) {
 		LLVMValueRef global = LLVMAddGlobal(p->module->mod, lb_type(p->module, e->type), c_name);
 		LLVMSetAlignment(global, cast(u32)type_align_of(e->type));
 		LLVMSetInitializer(global, LLVMConstNull(lb_type(p->module, e->type)));
-		if (value.value != nullptr) {
-			LLVMSetInitializer(global, value.value);
-		}
+
 		if (e->Variable.is_rodata) {
 			LLVMSetGlobalConstant(global, true);
 		}
-		if (e->Variable.thread_local_model != "") {
-			LLVMSetThreadLocal(global, true);
-
-			String m = e->Variable.thread_local_model;
-			LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel;
-			if (m == "default") {
-				mode = LLVMGeneralDynamicTLSModel;
-			} else if (m == "localdynamic") {
-				mode = LLVMLocalDynamicTLSModel;
-			} else if (m == "initialexec") {
-				mode = LLVMInitialExecTLSModel;
-			} else if (m == "localexec") {
-				mode = LLVMLocalExecTLSModel;
-			} else {
-				GB_PANIC("Unhandled thread local mode %.*s", LIT(m));
-			}
-			LLVMSetThreadLocalMode(global, mode);
-		} else {
+
+		if (!lb_apply_thread_local_model(global, e->Variable.thread_local_model)) {
 			LLVMSetLinkage(global, LLVMInternalLinkage);
 		}
 
+		if (value.value != nullptr) {
+			if (is_type_any(e->type)) {
+				Type *var_type = default_type(value.type);
+
+				gbString var_name = gb_string_make(temporary_allocator(), "__$static_any::");
+				var_name = gb_string_append_length(var_name, mangled_name.text, mangled_name.len);
+
+				lbAddr var_global = lb_add_global_generated_with_name(p->module, var_type, value, make_string_c(var_name), nullptr);
+				LLVMValueRef var_global_ref = var_global.addr.value;
+
+				if (e->Variable.is_rodata) {
+					LLVMSetGlobalConstant(var_global_ref, true);
+				}
+				
+				if (!lb_apply_thread_local_model(var_global_ref, e->Variable.thread_local_model)) {
+					LLVMSetLinkage(var_global_ref, LLVMInternalLinkage);
+				}
+
+				LLVMValueRef vals[2] = {
+					lb_emit_conv(p, var_global.addr, t_rawptr).value,
+					lb_typeid(p->module, var_type).value,
+				};
+				LLVMValueRef init = llvm_const_named_struct(p->module, e->type, vals, gb_count_of(vals));
+				LLVMSetInitializer(global, init);
+			} else {
+				LLVMSetInitializer(global, value.value);
+			}
+		}
 
 		lbValue global_val = {global, alloc_type_pointer(e->type)};
 		lb_add_entity(p->module, e, global_val);

+ 40 - 0
tests/internal/test_global_any.odin

@@ -0,0 +1,40 @@
+package test_internal
+
+@(private="file")
+global_any_from_proc: any = from_proc()
+
+from_proc :: proc() -> f32 {
+	return 1.1
+}
+
+@(private="file")
+global_any: any = 1
+
+import "core:testing"
+
+@(test)
+test_global_any :: proc(t: ^testing.T) {
+	as_f32, is_f32 := global_any_from_proc.(f32)
+	testing.expect(t, is_f32 == true)
+	testing.expect(t, as_f32 == 1.1)
+
+	as_int, is_int := global_any.(int)
+	testing.expect(t, is_int == true)
+	testing.expect(t, as_int == 1)
+}
+
+@(test)
+test_static_any :: proc(t: ^testing.T) {
+	@(static)
+	var: any = 3
+
+	as_int, is_int := var.(int)
+	testing.expect(t, is_int == true)
+	testing.expect(t, as_int == 3)
+
+	var = f32(1.1)
+
+	as_f32, is_f32 := var.(f32)
+	testing.expect(t, is_f32 == true)
+	testing.expect(t, as_f32 == 1.1)
+}