| author | |
| committer | |
| log | 04366576ea4be4959b596ebff7041d17e18d08d8 |
| tree | 94dceb8f1e846e09356e5b40b884791a7cc314eb |
| parent | 15f55b2805541276f491d255f60f501c8cbd1191 |
4 files changed, 38 insertions(+), 20 deletions(-)
src/Sema.zig+1-3| ... | @@ -6575,6 +6575,7 @@ fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -6575,6 +6575,7 @@ fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro |
| 6575 | const src = inst_data.src(); | 6575 | const src = inst_data.src(); |
| 6576 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 6576 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 6577 | const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); | 6577 | const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 6578 | try sema.resolveTypeLayout(block, src, operand_ty); | ||
| 6578 | const target = sema.mod.getTarget(); | 6579 | const target = sema.mod.getTarget(); |
| 6579 | const abi_size = switch (operand_ty.zigTypeTag()) { | 6580 | const abi_size = switch (operand_ty.zigTypeTag()) { |
| 6580 | .Fn => unreachable, | 6581 | .Fn => unreachable, |
| ... | @@ -10846,9 +10847,6 @@ pub fn resolveTypeLayout( | ... | @@ -10846,9 +10847,6 @@ pub fn resolveTypeLayout( |
| 10846 | ty: Type, | 10847 | ty: Type, |
| 10847 | ) CompileError!void { | 10848 | ) CompileError!void { |
| 10848 | switch (ty.zigTypeTag()) { | 10849 | switch (ty.zigTypeTag()) { |
| 10849 | .Pointer => { | ||
| 10850 | return sema.resolveTypeLayout(block, src, ty.elemType()); | ||
| 10851 | }, | ||
| 10852 | .Struct => { | 10850 | .Struct => { |
| 10853 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); | 10851 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 10854 | const struct_obj = resolved_ty.castTag(.@"struct").?.data; | 10852 | const struct_obj = resolved_ty.castTag(.@"struct").?.data; |
src/type.zig+15-1| ... | @@ -1765,7 +1765,21 @@ pub const Type = extern union { | ... | @@ -1765,7 +1765,21 @@ pub const Type = extern union { |
| 1765 | .@"struct" => { | 1765 | .@"struct" => { |
| 1766 | const s = self.castTag(.@"struct").?.data; | 1766 | const s = self.castTag(.@"struct").?.data; |
| 1767 | assert(s.status == .have_layout); | 1767 | assert(s.status == .have_layout); |
| 1768 | @panic("TODO abiSize struct"); | 1768 | const is_packed = s.layout == .Packed; |
| 1769 | if (is_packed) @panic("TODO packed structs"); | ||
| 1770 | var size: u64 = 0; | ||
| 1771 | for (s.fields.values()) |field| { | ||
| 1772 | const field_align = a: { | ||
| 1773 | if (field.abi_align.tag() == .abi_align_default) { | ||
| 1774 | break :a field.ty.abiAlignment(target); | ||
| 1775 | } else { | ||
| 1776 | break :a field.abi_align.toUnsignedInt(); | ||
| 1777 | } | ||
| 1778 | }; | ||
| 1779 | size = std.mem.alignForwardGeneric(u64, size, field_align); | ||
| 1780 | size += field.ty.abiSize(target); | ||
| 1781 | } | ||
| 1782 | return size; | ||
| 1769 | }, | 1783 | }, |
| 1770 | .enum_simple, .enum_full, .enum_nonexhaustive => { | 1784 | .enum_simple, .enum_full, .enum_nonexhaustive => { |
| 1771 | var buffer: Payload.Bits = undefined; | 1785 | var buffer: Payload.Bits = undefined; |
test/behavior/struct.zig+21| ... | @@ -31,3 +31,24 @@ test "return empty struct instance" { | ... | @@ -31,3 +31,24 @@ test "return empty struct instance" { |
| 31 | fn returnEmptyStructInstance() StructWithNoFields { | 31 | fn returnEmptyStructInstance() StructWithNoFields { |
| 32 | return empty_global_instance; | 32 | return empty_global_instance; |
| 33 | } | 33 | } |
| 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 | } |
test/behavior/struct_stage1.zig+1-16| ... | @@ -30,26 +30,11 @@ const VoidStructFieldsFoo = struct { | ... | @@ -30,26 +30,11 @@ const VoidStructFieldsFoo = struct { |
| 30 | c: void, | 30 | c: void, |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | test "structs" { | ||
| 34 | var foo: StructFoo = undefined; | ||
| 35 | @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); | ||
| 36 | foo.a += 1; | ||
| 37 | foo.b = foo.a == 1; | ||
| 38 | try testFoo(foo); | ||
| 39 | testMutation(&foo); | ||
| 40 | try expect(foo.c == 100); | ||
| 41 | } | ||
| 42 | const StructFoo = struct { | 33 | const StructFoo = struct { |
| 43 | a: i32, | 34 | a: i32, |
| 44 | b: bool, | 35 | b: bool, |
| 45 | c: f32, | 36 | c: f32, |
| 46 | }; | 37 | }; |
| 47 | fn testFoo(foo: StructFoo) !void { | ||
| 48 | try expect(foo.b); | ||
| 49 | } | ||
| 50 | fn testMutation(foo: *StructFoo) void { | ||
| 51 | foo.c = 100; | ||
| 52 | } | ||
| 53 | 38 | ||
| 54 | const Node = struct { | 39 | const Node = struct { |
| 55 | val: Val, | 40 | val: Val, |
| ... | @@ -84,7 +69,7 @@ test "struct byval assign" { | ... | @@ -84,7 +69,7 @@ test "struct byval assign" { |
| 84 | try expect(foo2.a == 1234); | 69 | try expect(foo2.a == 1234); |
| 85 | } | 70 | } |
| 86 | 71 | ||
| 87 | fn structInitializer() void { | 72 | test "struct initializer" { |
| 88 | const val = Val{ .x = 42 }; | 73 | const val = Val{ .x = 42 }; |
| 89 | try expect(val.x == 42); | 74 | try expect(val.x == 42); |
| 90 | } | 75 | } |