Commit 29f531bec9

Daniele Cocca <daniele.cocca@gmail.com>
2021-11-13 03:44:16
CBE: memset(..., 0xaa, ...) undefined values
This commit makes airStore() handle undefined values directly instead of delegating to renderValue(): the call to renderValue() happens too late, when "dest = " has already been written to the stream, at which point there's no sane way to initialize e.g. struct values by assignment. Instead, we make airStore() use memset(dest, 0xaa, sizeof(dest)), which should transparently handle all types. Also moves the newly-passing tests to the top of test/behavior.zig.
1 parent c61fbe7
Changed files (2)
src
codegen
test
src/codegen/c.zig
@@ -1470,12 +1470,51 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
     return local;
 }
 
+fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {
+    const is_debug_build = f.object.dg.module.optimizeMode() == .Debug;
+    if (!is_debug_build)
+        return CValue.none;
+
+    const writer = f.object.writer();
+    switch (dest_ptr) {
+        .local_ref => |i| {
+            const dest: CValue = .{ .local = i };
+            try writer.writeAll("memset(&");
+            try f.writeCValue(writer, dest);
+            try writer.writeAll(", 0xaa, sizeof(");
+            try f.writeCValue(writer, dest);
+            try writer.writeAll("));\n");
+        },
+        .decl_ref => |decl| {
+            const dest: CValue = .{ .decl = decl };
+            try writer.writeAll("memset(&");
+            try f.writeCValue(writer, dest);
+            try writer.writeAll(", 0xaa, sizeof(");
+            try f.writeCValue(writer, dest);
+            try writer.writeAll("));\n");
+        },
+        else => {
+            try writer.writeAll("memset(");
+            try f.writeCValue(writer, dest_ptr);
+            try writer.writeAll(", 0xaa, sizeof(*");
+            try f.writeCValue(writer, dest_ptr);
+            try writer.writeAll("));\n");
+        },
+    }
+    return CValue.none;
+}
+
 fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
     // *a = b;
     const bin_op = f.air.instructions.items(.data)[inst].bin_op;
     const dest_ptr = try f.resolveInst(bin_op.lhs);
     const src_val = try f.resolveInst(bin_op.rhs);
 
+    const src_val_is_undefined =
+        if (f.air.value(bin_op.rhs)) |v| v.isUndef() else false;
+    if (src_val_is_undefined)
+        return try airStoreUndefined(f, dest_ptr);
+
     const writer = f.object.writer();
     switch (dest_ptr) {
         .local_ref => |i| {
test/behavior.zig
@@ -5,12 +5,15 @@ test {
     _ = @import("behavior/basic.zig");
     _ = @import("behavior/bitcast.zig");
     _ = @import("behavior/bool.zig");
+    _ = @import("behavior/bugs/624.zig");
     _ = @import("behavior/bugs/655.zig");
     _ = @import("behavior/bugs/679.zig");
     _ = @import("behavior/bugs/704.zig");
     _ = @import("behavior/bugs/1486.zig");
     _ = @import("behavior/bugs/2346.zig");
+    _ = @import("behavior/bugs/2692.zig");
     _ = @import("behavior/bugs/2889.zig");
+    _ = @import("behavior/bugs/3586.zig");
     _ = @import("behavior/bugs/4560.zig");
     _ = @import("behavior/bugs/4769_a.zig");
     _ = @import("behavior/bugs/4769_b.zig");
@@ -30,6 +33,9 @@ test {
     _ = @import("behavior/underscore.zig");
     _ = @import("behavior/usingnamespace.zig");
     _ = @import("behavior/while.zig");
+    _ = @import("behavior/this.zig");
+    _ = @import("behavior/member_func.zig");
+    _ = @import("behavior/translate_c_macros.zig");
 
     if (builtin.object_format != .c) {
         // Tests that pass for stage1 and stage2 but not the C backend.
@@ -38,14 +44,11 @@ test {
         _ = @import("behavior/atomics.zig");
         _ = @import("behavior/basic_llvm.zig");
         _ = @import("behavior/bugs/394.zig");
-        _ = @import("behavior/bugs/624.zig");
         _ = @import("behavior/bugs/1277.zig");
         _ = @import("behavior/bugs/1500.zig");
         _ = @import("behavior/bugs/1741.zig");
         _ = @import("behavior/bugs/2006.zig");
-        _ = @import("behavior/bugs/2692.zig");
         _ = @import("behavior/bugs/3112.zig");
-        _ = @import("behavior/bugs/3586.zig");
         _ = @import("behavior/cast.zig");
         _ = @import("behavior/error.zig");
         _ = @import("behavior/eval.zig");
@@ -55,7 +58,6 @@ test {
         _ = @import("behavior/generics.zig");
         _ = @import("behavior/math.zig");
         _ = @import("behavior/maximum_minimum.zig");
-        _ = @import("behavior/member_func.zig");
         _ = @import("behavior/null_llvm.zig");
         _ = @import("behavior/optional.zig");
         _ = @import("behavior/pointers.zig");
@@ -65,8 +67,6 @@ test {
         _ = @import("behavior/slice.zig");
         _ = @import("behavior/struct_llvm.zig");
         _ = @import("behavior/switch.zig");
-        _ = @import("behavior/this.zig");
-        _ = @import("behavior/translate_c_macros.zig");
         _ = @import("behavior/union.zig");
         _ = @import("behavior/widening.zig");