authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-11-09 18:24:38-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-11-09 18:24:38-05:00
log7afa220f92dc0689116fc74935f6ddb73037f3c2
treeff0818274a1d4f2af7ce6f4cf6fd51d321addcfc
parentc715d512cbf513bc5a62a4b6022b037ee43900ba
parent684d9532c5ed0f8e213e6163d77d248ceb7393dd
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10102 from rainbowbismuth/c-while-tests

C backend: while, struct tests, better undefined global handling

4 files changed, 153 insertions(+), 97 deletions(-)

src/codegen/c.zig+15-1
...@@ -448,7 +448,14 @@ pub const DeclGen = struct {...@@ -448,7 +448,14 @@ pub const DeclGen = struct {
448 try w.writeAll("ZIG_COLD ");448 try w.writeAll("ZIG_COLD ");
449 }449 }
450 }450 }
451 try dg.renderType(w, dg.decl.ty.fnReturnType());451 const return_ty = dg.decl.ty.fnReturnType();
452 if (return_ty.hasCodeGenBits()) {
453 try dg.renderType(w, return_ty);
454 } else if (return_ty.zigTypeTag() == .NoReturn) {
455 try w.writeAll("zig_noreturn void");
456 } else {
457 try w.writeAll("void");
458 }
452 try w.writeAll(" ");459 try w.writeAll(" ");
453 try dg.renderDeclName(dg.decl, w);460 try dg.renderDeclName(dg.decl, w);
454 try w.writeAll("(");461 try w.writeAll("(");
...@@ -947,6 +954,10 @@ pub fn genDecl(o: *Object) !void {...@@ -947,6 +954,10 @@ pub fn genDecl(o: *Object) !void {
947 }954 }
948 try fwd_decl_writer.writeAll(";\n");955 try fwd_decl_writer.writeAll(";\n");
949956
957 if (variable.init.isUndef()) {
958 return;
959 }
960
950 try o.indent_writer.insertNewline();961 try o.indent_writer.insertNewline();
951 const w = o.writer();962 const w = o.writer();
952 try o.dg.renderType(w, o.dg.decl.ty);963 try o.dg.renderType(w, o.dg.decl.ty);
...@@ -1886,6 +1897,9 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -1886,6 +1897,9 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
1886}1897}
18871898
1888fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {1899fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
1900 if (f.liveness.isUnused(inst))
1901 return CValue.none;
1902
1889 const ty_op = f.air.instructions.items(.data)[inst].ty_op;1903 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
1890 const operand = try f.resolveInst(ty_op.operand);1904 const operand = try f.resolveInst(ty_op.operand);
18911905
test/behavior.zig+4-2
...@@ -21,12 +21,15 @@ test {...@@ -21,12 +21,15 @@ test {
21 _ = @import("behavior/hasdecl.zig");21 _ = @import("behavior/hasdecl.zig");
22 _ = @import("behavior/hasfield.zig");22 _ = @import("behavior/hasfield.zig");
23 _ = @import("behavior/if.zig");23 _ = @import("behavior/if.zig");
24 _ = @import("behavior/struct.zig");
25 _ = @import("behavior/truncate.zig");
24 _ = @import("behavior/null.zig");26 _ = @import("behavior/null.zig");
25 _ = @import("behavior/ptrcast.zig");27 _ = @import("behavior/ptrcast.zig");
26 _ = @import("behavior/pub_enum.zig");28 _ = @import("behavior/pub_enum.zig");
27 _ = @import("behavior/truncate.zig");29 _ = @import("behavior/truncate.zig");
28 _ = @import("behavior/underscore.zig");30 _ = @import("behavior/underscore.zig");
29 _ = @import("behavior/usingnamespace.zig");31 _ = @import("behavior/usingnamespace.zig");
32 _ = @import("behavior/while.zig");
3033
31 if (builtin.object_format != .c) {34 if (builtin.object_format != .c) {
32 // Tests that pass for stage1 and stage2 but not the C backend.35 // Tests that pass for stage1 and stage2 but not the C backend.
...@@ -60,12 +63,11 @@ test {...@@ -60,12 +63,11 @@ test {
60 _ = @import("behavior/saturating_arithmetic.zig");63 _ = @import("behavior/saturating_arithmetic.zig");
61 _ = @import("behavior/sizeof_and_typeof.zig");64 _ = @import("behavior/sizeof_and_typeof.zig");
62 _ = @import("behavior/slice.zig");65 _ = @import("behavior/slice.zig");
63 _ = @import("behavior/struct.zig");66 _ = @import("behavior/struct_llvm.zig");
64 _ = @import("behavior/switch.zig");67 _ = @import("behavior/switch.zig");
65 _ = @import("behavior/this.zig");68 _ = @import("behavior/this.zig");
66 _ = @import("behavior/translate_c_macros.zig");69 _ = @import("behavior/translate_c_macros.zig");
67 _ = @import("behavior/union.zig");70 _ = @import("behavior/union.zig");
68 _ = @import("behavior/while.zig");
69 _ = @import("behavior/widening.zig");71 _ = @import("behavior/widening.zig");
7072
71 if (builtin.zig_is_stage2) {73 if (builtin.zig_is_stage2) {
test/behavior/struct.zig-94
...@@ -32,38 +32,6 @@ fn returnEmptyStructInstance() StructWithNoFields {...@@ -32,38 +32,6 @@ fn returnEmptyStructInstance() StructWithNoFields {
32 return empty_global_instance;32 return empty_global_instance;
33}33}
3434
35const StructFoo = struct {
36 a: i32,
37 b: bool,
38 c: f32,
39};
40test "structs" {
41 var foo: StructFoo = undefined;
42 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
43 foo.a += 1;
44 foo.b = foo.a == 1;
45 try testFoo(foo);
46 testMutation(&foo);
47 try expect(foo.c == 100);
48}
49fn testFoo(foo: StructFoo) !void {
50 try expect(foo.b);
51}
52fn testMutation(foo: *StructFoo) void {
53 foo.c = 100;
54}
55
56test "struct byval assign" {
57 var foo1: StructFoo = undefined;
58 var foo2: StructFoo = undefined;
59
60 foo1.a = 1234;
61 foo2.a = 0;
62 try expect(foo2.a == 0);
63 foo2 = foo1;
64 try expect(foo2.a == 1234);
65}
66
67const Node = struct {35const Node = struct {
68 val: Val,36 val: Val,
69 next: *Node,37 next: *Node,
...@@ -90,65 +58,3 @@ test "call member function directly" {...@@ -90,65 +58,3 @@ test "call member function directly" {
90 const result = MemberFnTestFoo.member(instance);58 const result = MemberFnTestFoo.member(instance);
91 try expect(result == 1234);59 try expect(result == 1234);
92}60}
93
94test "struct point to self" {
95 var root: Node = undefined;
96 root.val.x = 1;
97
98 var node: Node = undefined;
99 node.next = &root;
100 node.val.x = 2;
101
102 root.next = &node;
103
104 try expect(node.next.next.next.val.x == 1);
105}
106
107test "void struct fields" {
108 const foo = VoidStructFieldsFoo{
109 .a = void{},
110 .b = 1,
111 .c = void{},
112 };
113 try expect(foo.b == 1);
114 try expect(@sizeOf(VoidStructFieldsFoo) == 4);
115}
116const VoidStructFieldsFoo = struct {
117 a: void,
118 b: i32,
119 c: void,
120};
121
122test "member functions" {
123 const r = MemberFnRand{ .seed = 1234 };
124 try expect(r.getSeed() == 1234);
125}
126const MemberFnRand = struct {
127 seed: u32,
128 pub fn getSeed(r: *const MemberFnRand) u32 {
129 return r.seed;
130 }
131};
132
133test "return struct byval from function" {
134 const bar = makeBar2(1234, 5678);
135 try expect(bar.y == 5678);
136}
137const Bar = struct {
138 x: i32,
139 y: i32,
140};
141fn makeBar2(x: i32, y: i32) Bar {
142 return Bar{
143 .x = x,
144 .y = y,
145 };
146}
147
148test "return empty struct from fn" {
149 _ = testReturnEmptyStructFromFn();
150}
151const EmptyStruct2 = struct {};
152fn testReturnEmptyStructFromFn() EmptyStruct2 {
153 return EmptyStruct2{};
154}
test/behavior/struct_llvm.zig created+134
...@@ -0,0 +1,134 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const native_endian = builtin.target.cpu.arch.endian();
4const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;
6const expectEqualSlices = std.testing.expectEqualSlices;
7const maxInt = std.math.maxInt;
8
9const StructWithNoFields = struct {
10 fn add(a: i32, b: i32) i32 {
11 return a + b;
12 }
13};
14
15const StructFoo = struct {
16 a: i32,
17 b: bool,
18 c: f32,
19};
20test "structs" {
21 var foo: StructFoo = undefined;
22 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
23 foo.a += 1;
24 foo.b = foo.a == 1;
25 try testFoo(foo);
26 testMutation(&foo);
27 try expect(foo.c == 100);
28}
29fn testFoo(foo: StructFoo) !void {
30 try expect(foo.b);
31}
32fn testMutation(foo: *StructFoo) void {
33 foo.c = 100;
34}
35
36test "struct byval assign" {
37 var foo1: StructFoo = undefined;
38 var foo2: StructFoo = undefined;
39
40 foo1.a = 1234;
41 foo2.a = 0;
42 try expect(foo2.a == 0);
43 foo2 = foo1;
44 try expect(foo2.a == 1234);
45}
46
47const Node = struct {
48 val: Val,
49 next: *Node,
50};
51
52const Val = struct {
53 x: i32,
54};
55
56test "struct initializer" {
57 const val = Val{ .x = 42 };
58 try expect(val.x == 42);
59}
60
61const MemberFnTestFoo = struct {
62 x: i32,
63 fn member(foo: MemberFnTestFoo) i32 {
64 return foo.x;
65 }
66};
67
68test "call member function directly" {
69 const instance = MemberFnTestFoo{ .x = 1234 };
70 const result = MemberFnTestFoo.member(instance);
71 try expect(result == 1234);
72}
73
74test "struct point to self" {
75 var root: Node = undefined;
76 root.val.x = 1;
77
78 var node: Node = undefined;
79 node.next = &root;
80 node.val.x = 2;
81
82 root.next = &node;
83
84 try expect(node.next.next.next.val.x == 1);
85}
86
87test "void struct fields" {
88 const foo = VoidStructFieldsFoo{
89 .a = void{},
90 .b = 1,
91 .c = void{},
92 };
93 try expect(foo.b == 1);
94 try expect(@sizeOf(VoidStructFieldsFoo) == 4);
95}
96const VoidStructFieldsFoo = struct {
97 a: void,
98 b: i32,
99 c: void,
100};
101
102test "member functions" {
103 const r = MemberFnRand{ .seed = 1234 };
104 try expect(r.getSeed() == 1234);
105}
106const MemberFnRand = struct {
107 seed: u32,
108 pub fn getSeed(r: *const MemberFnRand) u32 {
109 return r.seed;
110 }
111};
112
113test "return struct byval from function" {
114 const bar = makeBar2(1234, 5678);
115 try expect(bar.y == 5678);
116}
117const Bar = struct {
118 x: i32,
119 y: i32,
120};
121fn makeBar2(x: i32, y: i32) Bar {
122 return Bar{
123 .x = x,
124 .y = y,
125 };
126}
127
128test "return empty struct from fn" {
129 _ = testReturnEmptyStructFromFn();
130}
131const EmptyStruct2 = struct {};
132fn testReturnEmptyStructFromFn() EmptyStruct2 {
133 return EmptyStruct2{};
134}