mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
+4
-19
@@ -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 var_name = gb_string_make(permanent_allocator(), "__$global_any::");
|
||||||
gbString e_str = string_canonical_entity_name(temporary_allocator(), e);
|
gbString e_str = string_canonical_entity_name(temporary_allocator(), e);
|
||||||
var_name = gb_string_append_length(var_name, e_str, gb_strlen(e_str));
|
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);
|
lb_addr_store(p, g, var.init);
|
||||||
lbValue gp = lb_addr_get_ptr(p, g);
|
lbValue gp = lb_addr_get_ptr(p, g);
|
||||||
|
|
||||||
lbValue data = lb_emit_struct_ep(p, var.var, 0);
|
lbValue data = lb_emit_struct_ep(p, var.var, 0);
|
||||||
lbValue ti = lb_emit_struct_ep(p, var.var, 1);
|
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, 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 {
|
} else {
|
||||||
LLVMTypeRef vt = llvm_addr_type(p->module, var.var);
|
LLVMTypeRef vt = llvm_addr_type(p->module, var.var);
|
||||||
lbValue src0 = lb_emit_conv(p, var.init, t);
|
lbValue src0 = lb_emit_conv(p, var.init, t);
|
||||||
@@ -3194,24 +3194,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
|
|||||||
lbValue g = {};
|
lbValue g = {};
|
||||||
g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
|
g.value = LLVMAddGlobal(m->mod, lb_type(m, e->type), alloc_cstring(permanent_allocator(), name));
|
||||||
g.type = alloc_type_pointer(e->type);
|
g.type = alloc_type_pointer(e->type);
|
||||||
if (e->Variable.thread_local_model != "") {
|
|
||||||
LLVMSetThreadLocal(g.value, true);
|
|
||||||
|
|
||||||
String m = e->Variable.thread_local_model;
|
lb_apply_thread_local_model(g.value, 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);
|
|
||||||
}
|
|
||||||
if (is_foreign) {
|
if (is_foreign) {
|
||||||
LLVMSetLinkage(g.value, LLVMExternalLinkage);
|
LLVMSetLinkage(g.value, LLVMExternalLinkage);
|
||||||
LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass);
|
LLVMSetDLLStorageClass(g.value, LLVMDLLImportStorageClass);
|
||||||
|
|||||||
@@ -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) {
|
gb_internal void lb_add_edge(lbBlock *from, lbBlock *to) {
|
||||||
LLVMValueRef instr = LLVMGetLastInstruction(from->block);
|
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);
|
lb_set_entity_from_other_modules_linkage_correctly(other_module, e, name);
|
||||||
|
|
||||||
if (e->Variable.thread_local_model != "") {
|
lb_apply_thread_local_model(g.value, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-20
@@ -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);
|
LLVMValueRef global = LLVMAddGlobal(p->module->mod, lb_type(p->module, e->type), c_name);
|
||||||
LLVMSetAlignment(global, cast(u32)type_align_of(e->type));
|
LLVMSetAlignment(global, cast(u32)type_align_of(e->type));
|
||||||
LLVMSetInitializer(global, LLVMConstNull(lb_type(p->module, e->type)));
|
LLVMSetInitializer(global, LLVMConstNull(lb_type(p->module, e->type)));
|
||||||
if (value.value != nullptr) {
|
|
||||||
LLVMSetInitializer(global, value.value);
|
|
||||||
}
|
|
||||||
if (e->Variable.is_rodata) {
|
if (e->Variable.is_rodata) {
|
||||||
LLVMSetGlobalConstant(global, true);
|
LLVMSetGlobalConstant(global, true);
|
||||||
}
|
}
|
||||||
if (e->Variable.thread_local_model != "") {
|
|
||||||
LLVMSetThreadLocal(global, true);
|
|
||||||
|
|
||||||
String m = e->Variable.thread_local_model;
|
if (!lb_apply_thread_local_model(global, 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 {
|
|
||||||
LLVMSetLinkage(global, LLVMInternalLinkage);
|
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)};
|
lbValue global_val = {global, alloc_type_pointer(e->type)};
|
||||||
lb_add_entity(p->module, e, global_val);
|
lb_add_entity(p->module, e, global_val);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user