aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-11-24 10:57:18 +0000
committergingerBill <bill@gingerbill.org>2023-11-24 10:57:18 +0000
commit3102abf1aabdfff798cc0d2020c07c7138b59648 (patch)
tree92bc6b50887753e17e2ee85657da75d6a5c4403b /src
parentf809788f75f997ceebbbbfa0aa138f2ae2011e1e (diff)
mem zero rather than store to a union where the variant is of size zero
Diffstat (limited to 'src')
-rw-r--r--src/llvm_backend.hpp1
-rw-r--r--src/llvm_backend_general.cpp12
-rw-r--r--src/llvm_backend_utility.cpp4
3 files changed, 14 insertions, 3 deletions
diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp
index 5894dd38a..3e4070367 100644
--- a/src/llvm_backend.hpp
+++ b/src/llvm_backend.hpp
@@ -550,6 +550,7 @@ gb_internal LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLV
gb_internal void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile);
+gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile);
gb_internal gb_inline i64 lb_max_zero_init_size(void) {
return cast(i64)(4*build_context.int_size);
diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp
index fdcf94f29..c149ec853 100644
--- a/src/llvm_backend_general.cpp
+++ b/src/llvm_backend_general.cpp
@@ -1332,6 +1332,8 @@ gb_internal void lb_emit_store_union_variant(lbProcedure *p, lbValue parent, lbV
Type *pt = base_type(type_deref(parent.type));
GB_ASSERT(pt->kind == Type_Union);
if (pt->Union.kind == UnionType_shared_nil) {
+ GB_ASSERT(type_size_of(variant_type));
+
lbBlock *if_nil = lb_create_block(p, "shared_nil.if_nil");
lbBlock *if_not_nil = lb_create_block(p, "shared_nil.if_not_nil");
lbBlock *done = lb_create_block(p, "shared_nil.done");
@@ -1353,9 +1355,13 @@ gb_internal void lb_emit_store_union_variant(lbProcedure *p, lbValue parent, lbV
} else {
- lbValue underlying = lb_emit_conv(p, parent, alloc_type_pointer(variant_type));
-
- lb_emit_store(p, underlying, variant);
+ if (type_size_of(variant_type) == 0) {
+ unsigned alignment = 1;
+ lb_mem_zero_ptr_internal(p, parent.value, pt->Union.variant_block_size, alignment, false);
+ } else {
+ lbValue underlying = lb_emit_conv(p, parent, alloc_type_pointer(variant_type));
+ lb_emit_store(p, underlying, variant);
+ }
lb_emit_store_union_variant_tag(p, parent, variant_type);
}
}
diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp
index d8dbfd736..be3ae9c8a 100644
--- a/src/llvm_backend_utility.cpp
+++ b/src/llvm_backend_utility.cpp
@@ -57,6 +57,10 @@ gb_internal lbValue lb_correct_endianness(lbProcedure *p, lbValue value) {
return value;
}
+gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile) {
+ return lb_mem_zero_ptr_internal(p, ptr, LLVMConstInt(lb_type(p->module, t_uint), len, false), alignment, is_volatile);
+}
+
gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) {
bool is_inlinable = false;