aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-12-08 15:00:07 +0000
committergingerBill <bill@gingerbill.org>2020-12-08 15:00:07 +0000
commit83cd2473f266870c66686e643b7898f6812e122c (patch)
treee350eca3e491bf92e46412dc8bb4b6416b6f1428 /src/ir.cpp
parent510d1f251889507d0c14086dfd8b46af97adf8b6 (diff)
Improve rules for zeroing types with the ir.cpp backend with `ir_type_requires_mem_zero`
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp66
1 files changed, 64 insertions, 2 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index e46eb27fb..244666dd9 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -3162,14 +3162,76 @@ void ir_value_set_debug_location(irProcedure *proc, irValue *v) {
}
}
+bool ir_type_requires_mem_zero(Type *t) {
+ t = core_type(t);
+ isize sz = type_size_of(t);
+ if (t->kind == Type_SimdVector) {
+ return false;
+ }
+
+ if (!(gb_is_power_of_two(sz) && sz <= build_context.max_align)) {
+ return true;
+ }
+
+ enum : i64 {LARGE_SIZE = 64};
+ if (sz > LARGE_SIZE) {
+ return true;
+ }
+
+ switch (t->kind) {
+ case Type_Union:
+ return true;
+ case Type_Struct:
+ if (t->Struct.is_raw_union) {
+ return true;
+ }
+ if (t->Struct.is_packed) {
+ return false;
+ } else {
+ i64 packed_sized = 0;
+ for_array(i, t->Struct.fields) {
+ Type *f = t->Struct.fields[i];
+ if (f->kind == Entity_Variable) {
+ packed_sized += type_size_of(f->type);
+ }
+ }
+ return sz != packed_sized;
+ }
+ break;
+ case Type_Tuple:
+ if (t->Tuple.is_packed) {
+ return false;
+ } else {
+ i64 packed_sized = 0;
+ for_array(i, t->Tuple.variables) {
+ Entity *f = t->Tuple.variables[i];
+ if (f->kind == Entity_Variable) {
+ packed_sized += type_size_of(f->type);
+ }
+ }
+ return sz != packed_sized;
+ }
+ break;
+
+ case Type_DynamicArray:
+ case Type_Map:
+ case Type_BitField:
+ return true;
+ case Type_Array:
+ return ir_type_requires_mem_zero(t->Array.elem);
+ case Type_EnumeratedArray:
+ return ir_type_requires_mem_zero(t->EnumeratedArray.elem);
+ }
+ return false;
+}
+
void ir_emit_zero_init(irProcedure *p, irValue *address, Ast *expr) {
gbAllocator a = ir_allocator();
Type *t = type_deref(ir_type(address));
- isize sz = type_size_of(t);
if (address) address->uses += 1;
- if (!(gb_is_power_of_two(sz) && sz <= build_context.max_align)) {
+ if (ir_type_requires_mem_zero(t)) {
// TODO(bill): Is this a good idea?
auto args = array_make<irValue *>(a, 2);
args[0] = ir_emit_conv(p, address, t_rawptr);