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.
This commit is contained in:
Daniele Cocca 2021-11-13 02:44:16 +00:00 committed by Andrew Kelley
parent c61fbe77c8
commit 29f531bec9
2 changed files with 45 additions and 6 deletions

View File

@ -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| {

View File

@ -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");