authorgravatar for reserveblue@protonmail.comdrew <reserveblue@protonmail.com> 2021-11-14 23:27:13-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-16 16:51:31-07:00
logcf99afc52568ab121db2db8aa3ba94b97109f396
treee7ed54a202c88c7a04753b24850308768d12dac8
parent3896de307888d598cca1baba8e559debc81d2080

add generics behavior test

-airLoad and airStore now properly report an error if they are used with an array, instead of having the C compiler emit a vague error -airStoreUndefined now works with array types -structFieldPtr now works with array types, allowing generics' tests to pass

2 files changed, 17 insertions(+), 6 deletions(-)

src/codegen/c.zig+16-5
...@@ -1431,6 +1431,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -1431,6 +1431,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
1431 if (!is_volatile and f.liveness.isUnused(inst))1431 if (!is_volatile and f.liveness.isUnused(inst))
1432 return CValue.none;1432 return CValue.none;
1433 const inst_ty = f.air.typeOfIndex(inst);1433 const inst_ty = f.air.typeOfIndex(inst);
1434 if (inst_ty.zigTypeTag() == .Array)
1435 return f.fail("TODO: C backend: implement airLoad for arrays", .{});
1434 const operand = try f.resolveInst(ty_op.operand);1436 const operand = try f.resolveInst(ty_op.operand);
1435 const writer = f.object.writer();1437 const writer = f.object.writer();
1436 const local = try f.allocLocal(inst_ty, .Const);1438 const local = try f.allocLocal(inst_ty, .Const);
...@@ -1557,7 +1559,7 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -1557,7 +1559,7 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
1557 return local;1559 return local;
1558}1560}
15591561
1560fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {1562fn airStoreUndefined(f: *Function, dest_ptr: CValue, dest_type: Type) !CValue {
1561 const is_debug_build = f.object.dg.module.optimizeMode() == .Debug;1563 const is_debug_build = f.object.dg.module.optimizeMode() == .Debug;
1562 if (!is_debug_build)1564 if (!is_debug_build)
1563 return CValue.none;1565 return CValue.none;
...@@ -1581,9 +1583,11 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {...@@ -1581,9 +1583,11 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {
1581 try writer.writeAll("));\n");1583 try writer.writeAll("));\n");
1582 },1584 },
1583 else => {1585 else => {
1586 const indirection = if (dest_type.zigTypeTag() == .Array) "" else "*";
1587
1584 try writer.writeAll("memset(");1588 try writer.writeAll("memset(");
1585 try f.writeCValue(writer, dest_ptr);1589 try f.writeCValue(writer, dest_ptr);
1586 try writer.writeAll(", 0xaa, sizeof(*");1590 try writer.print(", 0xaa, sizeof({s}", .{indirection});
1587 try f.writeCValue(writer, dest_ptr);1591 try f.writeCValue(writer, dest_ptr);
1588 try writer.writeAll("));\n");1592 try writer.writeAll("));\n");
1589 },1593 },
...@@ -1596,11 +1600,16 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -1596,11 +1600,16 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
1596 const bin_op = f.air.instructions.items(.data)[inst].bin_op;1600 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
1597 const dest_ptr = try f.resolveInst(bin_op.lhs);1601 const dest_ptr = try f.resolveInst(bin_op.lhs);
1598 const src_val = try f.resolveInst(bin_op.rhs);1602 const src_val = try f.resolveInst(bin_op.rhs);
1603 const lhs_type = f.air.typeOf(bin_op.lhs);
15991604
1600 const src_val_is_undefined =1605 const src_val_is_undefined =
1601 if (f.air.value(bin_op.rhs)) |v| v.isUndef() else false;1606 if (f.air.value(bin_op.rhs)) |v| v.isUndef() else false;
1602 if (src_val_is_undefined)1607 if (src_val_is_undefined)
1603 return try airStoreUndefined(f, dest_ptr);1608 return try airStoreUndefined(f, dest_ptr, lhs_type);
1609
1610 // Don't check this for airStoreUndefined as that will work for arrays already
1611 if (lhs_type.zigTypeTag() == .Array)
1612 return f.fail("TODO: C backend: implement airStore for arrays", .{});
16041613
1605 const writer = f.object.writer();1614 const writer = f.object.writer();
1606 switch (dest_ptr) {1615 switch (dest_ptr) {
...@@ -2420,15 +2429,17 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc...@@ -2420,15 +2429,17 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
2420 const writer = f.object.writer();2429 const writer = f.object.writer();
2421 const struct_obj = struct_ptr_ty.elemType().castTag(.@"struct").?.data;2430 const struct_obj = struct_ptr_ty.elemType().castTag(.@"struct").?.data;
2422 const field_name = struct_obj.fields.keys()[index];2431 const field_name = struct_obj.fields.keys()[index];
2432 const field_val = struct_obj.fields.values()[index];
2433 const addrof = if (field_val.ty.zigTypeTag() == .Array) "" else "&";
24232434
2424 const inst_ty = f.air.typeOfIndex(inst);2435 const inst_ty = f.air.typeOfIndex(inst);
2425 const local = try f.allocLocal(inst_ty, .Const);2436 const local = try f.allocLocal(inst_ty, .Const);
2426 switch (struct_ptr) {2437 switch (struct_ptr) {
2427 .local_ref => |i| {2438 .local_ref => |i| {
2428 try writer.print(" = &t{d}.{};\n", .{ i, fmtIdent(field_name) });2439 try writer.print(" = {s}t{d}.{};\n", .{ addrof, i, fmtIdent(field_name) });
2429 },2440 },
2430 else => {2441 else => {
2431 try writer.writeAll(" = &");2442 try writer.print(" = {s}", .{addrof});
2432 try f.writeCValue(writer, struct_ptr);2443 try f.writeCValue(writer, struct_ptr);
2433 try writer.print("->{};\n", .{fmtIdent(field_name)});2444 try writer.print("->{};\n", .{fmtIdent(field_name)});
2434 },2445 },
test/behavior.zig+1-1
...@@ -38,6 +38,7 @@ test {...@@ -38,6 +38,7 @@ test {
38 _ = @import("behavior/this.zig");38 _ = @import("behavior/this.zig");
39 _ = @import("behavior/member_func.zig");39 _ = @import("behavior/member_func.zig");
40 _ = @import("behavior/translate_c_macros.zig");40 _ = @import("behavior/translate_c_macros.zig");
41 _ = @import("behavior/generics.zig");
4142
42 if (builtin.object_format != .c) {43 if (builtin.object_format != .c) {
43 // Tests that pass for stage1 and stage2 but not the C backend.44 // Tests that pass for stage1 and stage2 but not the C backend.
...@@ -57,7 +58,6 @@ test {...@@ -57,7 +58,6 @@ test {
57 _ = @import("behavior/floatop.zig");58 _ = @import("behavior/floatop.zig");
58 _ = @import("behavior/fn.zig");59 _ = @import("behavior/fn.zig");
59 _ = @import("behavior/for.zig");60 _ = @import("behavior/for.zig");
60 _ = @import("behavior/generics.zig");
61 _ = @import("behavior/math.zig");61 _ = @import("behavior/math.zig");
62 _ = @import("behavior/maximum_minimum.zig");62 _ = @import("behavior/maximum_minimum.zig");
63 _ = @import("behavior/null_llvm.zig");63 _ = @import("behavior/null_llvm.zig");