From 04366576ea4be4959b596ebff7041d17e18d08d8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 25 Sep 2021 17:52:50 -0700 Subject: [PATCH] stage2: implement `@sizeOf` for non-packed structs --- src/Sema.zig | 4 +--- src/type.zig | 16 +++++++++++++++- test/behavior/struct.zig | 21 +++++++++++++++++++++ test/behavior/struct_stage1.zig | 17 +---------------- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 41fabbfacd..1001b388a9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -6575,6 +6575,7 @@ fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); + try sema.resolveTypeLayout(block, src, operand_ty); const target = sema.mod.getTarget(); const abi_size = switch (operand_ty.zigTypeTag()) { .Fn => unreachable, @@ -10846,9 +10847,6 @@ pub fn resolveTypeLayout( ty: Type, ) CompileError!void { switch (ty.zigTypeTag()) { - .Pointer => { - return sema.resolveTypeLayout(block, src, ty.elemType()); - }, .Struct => { const resolved_ty = try sema.resolveTypeFields(block, src, ty); const struct_obj = resolved_ty.castTag(.@"struct").?.data; diff --git a/src/type.zig b/src/type.zig index 0381111345..bd008e809a 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1765,7 +1765,21 @@ pub const Type = extern union { .@"struct" => { const s = self.castTag(.@"struct").?.data; assert(s.status == .have_layout); - @panic("TODO abiSize struct"); + const is_packed = s.layout == .Packed; + if (is_packed) @panic("TODO packed structs"); + var size: u64 = 0; + for (s.fields.values()) |field| { + const field_align = a: { + if (field.abi_align.tag() == .abi_align_default) { + break :a field.ty.abiAlignment(target); + } else { + break :a field.abi_align.toUnsignedInt(); + } + }; + size = std.mem.alignForwardGeneric(u64, size, field_align); + size += field.ty.abiSize(target); + } + return size; }, .enum_simple, .enum_full, .enum_nonexhaustive => { var buffer: Payload.Bits = undefined; diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 6f00b71057..e048848799 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -31,3 +31,24 @@ test "return empty struct instance" { fn returnEmptyStructInstance() StructWithNoFields { return empty_global_instance; } + +const StructFoo = struct { + a: i32, + b: bool, + c: f32, +}; +test "structs" { + var foo: StructFoo = undefined; + @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); + foo.a += 1; + foo.b = foo.a == 1; + try testFoo(foo); + testMutation(&foo); + try expect(foo.c == 100); +} +fn testFoo(foo: StructFoo) !void { + try expect(foo.b); +} +fn testMutation(foo: *StructFoo) void { + foo.c = 100; +} diff --git a/test/behavior/struct_stage1.zig b/test/behavior/struct_stage1.zig index 9f084ceb85..fd19b37661 100644 --- a/test/behavior/struct_stage1.zig +++ b/test/behavior/struct_stage1.zig @@ -30,26 +30,11 @@ const VoidStructFieldsFoo = struct { c: void, }; -test "structs" { - var foo: StructFoo = undefined; - @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); - foo.a += 1; - foo.b = foo.a == 1; - try testFoo(foo); - testMutation(&foo); - try expect(foo.c == 100); -} const StructFoo = struct { a: i32, b: bool, c: f32, }; -fn testFoo(foo: StructFoo) !void { - try expect(foo.b); -} -fn testMutation(foo: *StructFoo) void { - foo.c = 100; -} const Node = struct { val: Val, @@ -84,7 +69,7 @@ test "struct byval assign" { try expect(foo2.a == 1234); } -fn structInitializer() void { +test "struct initializer" { const val = Val{ .x = 42 }; try expect(val.x == 42); }