| author | |
| committer | |
| log | 7afa220f92dc0689116fc74935f6ddb73037f3c2 |
| tree | ff0818274a1d4f2af7ce6f4cf6fd51d321addcfc |
| parent | c715d512cbf513bc5a62a4b6022b037ee43900ba |
| parent | 684d9532c5ed0f8e213e6163d77d248ceb7393dd |
| signature |
C backend: while, struct tests, better undefined global handling4 files changed, 153 insertions(+), 97 deletions(-)
src/codegen/c.zig+15-1| ... | ... | @@ -448,7 +448,14 @@ pub const DeclGen = struct { |
| 448 | 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 | 459 | try w.writeAll(" "); |
| 453 | 460 | try dg.renderDeclName(dg.decl, w); |
| 454 | 461 | try w.writeAll("("); |
| ... | ... | @@ -947,6 +954,10 @@ pub fn genDecl(o: *Object) !void { |
| 947 | 954 | } |
| 948 | 955 | try fwd_decl_writer.writeAll(";\n"); |
| 949 | 956 | |
| 957 | if (variable.init.isUndef()) { | |
| 958 | return; | |
| 959 | } | |
| 960 | ||
| 950 | 961 | try o.indent_writer.insertNewline(); |
| 951 | 962 | const w = o.writer(); |
| 952 | 963 | try o.dg.renderType(w, o.dg.decl.ty); |
| ... | ... | @@ -1886,6 +1897,9 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 1886 | 1897 | } |
| 1887 | 1898 | |
| 1888 | 1899 | fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 1900 | if (f.liveness.isUnused(inst)) | |
| 1901 | return CValue.none; | |
| 1902 | ||
| 1889 | 1903 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 1890 | 1904 | const operand = try f.resolveInst(ty_op.operand); |
| 1891 | 1905 |
test/behavior.zig+4-2| ... | ... | @@ -21,12 +21,15 @@ test { |
| 21 | 21 | _ = @import("behavior/hasdecl.zig"); |
| 22 | 22 | _ = @import("behavior/hasfield.zig"); |
| 23 | 23 | _ = @import("behavior/if.zig"); |
| 24 | _ = @import("behavior/struct.zig"); | |
| 25 | _ = @import("behavior/truncate.zig"); | |
| 24 | 26 | _ = @import("behavior/null.zig"); |
| 25 | 27 | _ = @import("behavior/ptrcast.zig"); |
| 26 | 28 | _ = @import("behavior/pub_enum.zig"); |
| 27 | 29 | _ = @import("behavior/truncate.zig"); |
| 28 | 30 | _ = @import("behavior/underscore.zig"); |
| 29 | 31 | _ = @import("behavior/usingnamespace.zig"); |
| 32 | _ = @import("behavior/while.zig"); | |
| 30 | 33 | |
| 31 | 34 | if (builtin.object_format != .c) { |
| 32 | 35 | // Tests that pass for stage1 and stage2 but not the C backend. |
| ... | ... | @@ -60,12 +63,11 @@ test { |
| 60 | 63 | _ = @import("behavior/saturating_arithmetic.zig"); |
| 61 | 64 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| 62 | 65 | _ = @import("behavior/slice.zig"); |
| 63 | _ = @import("behavior/struct.zig"); | |
| 66 | _ = @import("behavior/struct_llvm.zig"); | |
| 64 | 67 | _ = @import("behavior/switch.zig"); |
| 65 | 68 | _ = @import("behavior/this.zig"); |
| 66 | 69 | _ = @import("behavior/translate_c_macros.zig"); |
| 67 | 70 | _ = @import("behavior/union.zig"); |
| 68 | _ = @import("behavior/while.zig"); | |
| 69 | 71 | _ = @import("behavior/widening.zig"); |
| 70 | 72 | |
| 71 | 73 | if (builtin.zig_is_stage2) { |
test/behavior/struct.zig-94| ... | ... | @@ -32,38 +32,6 @@ fn returnEmptyStructInstance() StructWithNoFields { |
| 32 | 32 | return empty_global_instance; |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | const StructFoo = struct { | |
| 36 | a: i32, | |
| 37 | b: bool, | |
| 38 | c: f32, | |
| 39 | }; | |
| 40 | test "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 | } | |
| 49 | fn testFoo(foo: StructFoo) !void { | |
| 50 | try expect(foo.b); | |
| 51 | } | |
| 52 | fn testMutation(foo: *StructFoo) void { | |
| 53 | foo.c = 100; | |
| 54 | } | |
| 55 | ||
| 56 | test "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 | ||
| 67 | 35 | const Node = struct { |
| 68 | 36 | val: Val, |
| 69 | 37 | next: *Node, |
| ... | ... | @@ -90,65 +58,3 @@ test "call member function directly" { |
| 90 | 58 | const result = MemberFnTestFoo.member(instance); |
| 91 | 59 | try expect(result == 1234); |
| 92 | 60 | } |
| 93 | ||
| 94 | test "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 | ||
| 107 | test "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 | } | |
| 116 | const VoidStructFieldsFoo = struct { | |
| 117 | a: void, | |
| 118 | b: i32, | |
| 119 | c: void, | |
| 120 | }; | |
| 121 | ||
| 122 | test "member functions" { | |
| 123 | const r = MemberFnRand{ .seed = 1234 }; | |
| 124 | try expect(r.getSeed() == 1234); | |
| 125 | } | |
| 126 | const MemberFnRand = struct { | |
| 127 | seed: u32, | |
| 128 | pub fn getSeed(r: *const MemberFnRand) u32 { | |
| 129 | return r.seed; | |
| 130 | } | |
| 131 | }; | |
| 132 | ||
| 133 | test "return struct byval from function" { | |
| 134 | const bar = makeBar2(1234, 5678); | |
| 135 | try expect(bar.y == 5678); | |
| 136 | } | |
| 137 | const Bar = struct { | |
| 138 | x: i32, | |
| 139 | y: i32, | |
| 140 | }; | |
| 141 | fn makeBar2(x: i32, y: i32) Bar { | |
| 142 | return Bar{ | |
| 143 | .x = x, | |
| 144 | .y = y, | |
| 145 | }; | |
| 146 | } | |
| 147 | ||
| 148 | test "return empty struct from fn" { | |
| 149 | _ = testReturnEmptyStructFromFn(); | |
| 150 | } | |
| 151 | const EmptyStruct2 = struct {}; | |
| 152 | fn testReturnEmptyStructFromFn() EmptyStruct2 { | |
| 153 | return EmptyStruct2{}; | |
| 154 | } |
test/behavior/struct_llvm.zig created+134| ... | ... | @@ -0,0 +1,134 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const native_endian = builtin.target.cpu.arch.endian(); | |
| 4 | const expect = std.testing.expect; | |
| 5 | const expectEqual = std.testing.expectEqual; | |
| 6 | const expectEqualSlices = std.testing.expectEqualSlices; | |
| 7 | const maxInt = std.math.maxInt; | |
| 8 | ||
| 9 | const StructWithNoFields = struct { | |
| 10 | fn add(a: i32, b: i32) i32 { | |
| 11 | return a + b; | |
| 12 | } | |
| 13 | }; | |
| 14 | ||
| 15 | const StructFoo = struct { | |
| 16 | a: i32, | |
| 17 | b: bool, | |
| 18 | c: f32, | |
| 19 | }; | |
| 20 | test "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 | } | |
| 29 | fn testFoo(foo: StructFoo) !void { | |
| 30 | try expect(foo.b); | |
| 31 | } | |
| 32 | fn testMutation(foo: *StructFoo) void { | |
| 33 | foo.c = 100; | |
| 34 | } | |
| 35 | ||
| 36 | test "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 | ||
| 47 | const Node = struct { | |
| 48 | val: Val, | |
| 49 | next: *Node, | |
| 50 | }; | |
| 51 | ||
| 52 | const Val = struct { | |
| 53 | x: i32, | |
| 54 | }; | |
| 55 | ||
| 56 | test "struct initializer" { | |
| 57 | const val = Val{ .x = 42 }; | |
| 58 | try expect(val.x == 42); | |
| 59 | } | |
| 60 | ||
| 61 | const MemberFnTestFoo = struct { | |
| 62 | x: i32, | |
| 63 | fn member(foo: MemberFnTestFoo) i32 { | |
| 64 | return foo.x; | |
| 65 | } | |
| 66 | }; | |
| 67 | ||
| 68 | test "call member function directly" { | |
| 69 | const instance = MemberFnTestFoo{ .x = 1234 }; | |
| 70 | const result = MemberFnTestFoo.member(instance); | |
| 71 | try expect(result == 1234); | |
| 72 | } | |
| 73 | ||
| 74 | test "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 | ||
| 87 | test "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 | } | |
| 96 | const VoidStructFieldsFoo = struct { | |
| 97 | a: void, | |
| 98 | b: i32, | |
| 99 | c: void, | |
| 100 | }; | |
| 101 | ||
| 102 | test "member functions" { | |
| 103 | const r = MemberFnRand{ .seed = 1234 }; | |
| 104 | try expect(r.getSeed() == 1234); | |
| 105 | } | |
| 106 | const MemberFnRand = struct { | |
| 107 | seed: u32, | |
| 108 | pub fn getSeed(r: *const MemberFnRand) u32 { | |
| 109 | return r.seed; | |
| 110 | } | |
| 111 | }; | |
| 112 | ||
| 113 | test "return struct byval from function" { | |
| 114 | const bar = makeBar2(1234, 5678); | |
| 115 | try expect(bar.y == 5678); | |
| 116 | } | |
| 117 | const Bar = struct { | |
| 118 | x: i32, | |
| 119 | y: i32, | |
| 120 | }; | |
| 121 | fn makeBar2(x: i32, y: i32) Bar { | |
| 122 | return Bar{ | |
| 123 | .x = x, | |
| 124 | .y = y, | |
| 125 | }; | |
| 126 | } | |
| 127 | ||
| 128 | test "return empty struct from fn" { | |
| 129 | _ = testReturnEmptyStructFromFn(); | |
| 130 | } | |
| 131 | const EmptyStruct2 = struct {}; | |
| 132 | fn testReturnEmptyStructFromFn() EmptyStruct2 { | |
| 133 | return EmptyStruct2{}; | |
| 134 | } |