Commit 04366576ea

Andrew Kelley <andrew@ziglang.org>
2021-09-26 02:52:50
stage2: implement `@sizeOf` for non-packed structs
1 parent 15f55b2
Changed files (4)
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;
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;
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;
+}
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);
 }