aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-12-08 15:43:57 +0000
committergingerBill <bill@gingerbill.org>2020-12-08 15:43:57 +0000
commitd7a5767aa3497f9b4b6f0ced955ce31fb019ef80 (patch)
treef5afd9187de1a01433b82a9cc27f5258cc6802ed /src/ir.cpp
parent15bf57e4e193f8e5a545517210526fb7144048e8 (diff)
If `ir_type_requires_mem_zero` is stored with zero, don't store again with the `zeroinitializer`
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp192
1 files changed, 114 insertions, 78 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 34b64562f..f69b25494 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -901,7 +901,7 @@ Array<irValue *> *ir_value_referrers(irValue *v) {
////////////////////////////////////////////////////////////////
void ir_module_add_value (irModule *m, Entity *e, irValue *v);
-void ir_emit_zero_init (irProcedure *p, irValue *address, Ast *expr);
+irValue *ir_emit_zero_init (irProcedure *p, irValue *address, Ast *expr);
irValue *ir_emit_comment (irProcedure *p, String text);
irValue *ir_emit_store (irProcedure *p, irValue *address, irValue *value, bool is_volatile=false);
irValue *ir_emit_load (irProcedure *p, irValue *address, i64 custom_align=0);
@@ -3091,6 +3091,85 @@ void ir_pop_debug_location(irModule *m) {
irValue *ir_emit_runtime_call(irProcedure *proc, char const *name_, Array<irValue *> args, Ast *expr = nullptr, ProcInlining inlining = ProcInlining_none);
irValue *ir_emit_package_call(irProcedure *proc, char const *package_name_, char const *name_, Array<irValue *> args, Ast *expr = nullptr, ProcInlining inlining = ProcInlining_none);
+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) {
+ Entity *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;
+}
+
+irValue *ir_call_mem_zero(irProcedure *p, irValue *address, Ast *expr = nullptr) {
+ Type *t = type_deref(ir_type(address));
+ // TODO(bill): Is this a good idea?
+ auto args = array_make<irValue *>(ir_allocator(), 2);
+ args[0] = ir_emit_conv(p, address, t_rawptr);
+ args[1] = ir_const_int(type_size_of(t));
+ AstPackage *pkg_runtime = get_core_package(p->module->info, str_lit("runtime"));
+ if (p->entity != nullptr) {
+ String name = p->entity->token.string;
+ if (p->entity->pkg != pkg_runtime && !(name == "mem_zero" || name == "memset")) {
+ ir_emit_comment(p, str_lit("ZeroInit"));
+ return ir_emit_package_call(p, "runtime", "mem_zero", args, expr);
+ }
+ }
+ return nullptr;
+}
irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value, bool is_volatile) {
Type *a = type_deref(ir_type(address));
@@ -3108,6 +3187,35 @@ irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value, bool is
if (!is_type_untyped(b)) {
GB_ASSERT_MSG(are_types_identical(core_type(a), core_type(b)), "%s %s", type_to_string(a), type_to_string(b));
}
+
+
+ if (value->kind == irValue_Constant) {
+ ExactValue const &v = value->Constant.value;
+ irValue *res = nullptr;
+ switch (v.kind) {
+ case ExactValue_Invalid:
+ res = ir_call_mem_zero(p, address);
+ if (res) {
+ return res;
+ }
+ goto end;
+
+ case ExactValue_Compound:
+ // NOTE(bill): This is to enforce the zeroing of the padding
+ if (ir_type_requires_mem_zero(a)) {
+ res = ir_call_mem_zero(p, address);
+ if (res == nullptr || v.value_compound == nullptr) {
+ goto end;
+ }
+ if (is_exact_value_zero(v)) {
+ return res;
+ }
+ }
+ goto end;
+ }
+ }
+
+end:;
return ir_emit(p, ir_instr_store(p, address, value, is_volatile));
}
irValue *ir_emit_load(irProcedure *p, irValue *address, i64 custom_align) {
@@ -3162,91 +3270,19 @@ 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) {
- Entity *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) {
+irValue *ir_emit_zero_init(irProcedure *p, irValue *address, Ast *expr) {
gbAllocator a = ir_allocator();
Type *t = type_deref(ir_type(address));
if (address) address->uses += 1;
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);
- args[1] = ir_const_int(type_size_of(t));
- AstPackage *pkg_runtime = get_core_package(p->module->info, str_lit("runtime"));
- if (p->entity != nullptr) {
- String name = p->entity->token.string;
- if (p->entity->pkg != pkg_runtime && !(name == "mem_zero" || name == "memset")) {
- ir_emit_comment(p, str_lit("ZeroInit"));
- irValue *v = ir_emit_package_call(p, "runtime", "mem_zero", args, expr);
- return;
- }
+ irValue *res = ir_call_mem_zero(p, address, expr);
+ if (res) {
+ return res;
}
}
- ir_emit(p, ir_instr_zero_init(p, address));
+ return ir_emit(p, ir_instr_zero_init(p, address));
}
irValue *ir_emit_comment(irProcedure *p, String text) {