stage2: implement @sizeOf for non-packed structs

This commit is contained in:
Andrew Kelley 2021-09-25 17:52:50 -07:00
parent 15f55b2805
commit 04366576ea
4 changed files with 38 additions and 20 deletions

View File

@ -6575,6 +6575,7 @@ fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro
const src = inst_data.src(); const src = inst_data.src();
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; 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); 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 target = sema.mod.getTarget();
const abi_size = switch (operand_ty.zigTypeTag()) { const abi_size = switch (operand_ty.zigTypeTag()) {
.Fn => unreachable, .Fn => unreachable,
@ -10846,9 +10847,6 @@ pub fn resolveTypeLayout(
ty: Type, ty: Type,
) CompileError!void { ) CompileError!void {
switch (ty.zigTypeTag()) { switch (ty.zigTypeTag()) {
.Pointer => {
return sema.resolveTypeLayout(block, src, ty.elemType());
},
.Struct => { .Struct => {
const resolved_ty = try sema.resolveTypeFields(block, src, ty); const resolved_ty = try sema.resolveTypeFields(block, src, ty);
const struct_obj = resolved_ty.castTag(.@"struct").?.data; const struct_obj = resolved_ty.castTag(.@"struct").?.data;

View File

@ -1765,7 +1765,21 @@ pub const Type = extern union {
.@"struct" => { .@"struct" => {
const s = self.castTag(.@"struct").?.data; const s = self.castTag(.@"struct").?.data;
assert(s.status == .have_layout); 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 => { .enum_simple, .enum_full, .enum_nonexhaustive => {
var buffer: Payload.Bits = undefined; var buffer: Payload.Bits = undefined;

View File

@ -31,3 +31,24 @@ test "return empty struct instance" {
fn returnEmptyStructInstance() StructWithNoFields { fn returnEmptyStructInstance() StructWithNoFields {
return empty_global_instance; 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;
}

View File

@ -30,26 +30,11 @@ const VoidStructFieldsFoo = struct {
c: void, 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 { const StructFoo = struct {
a: i32, a: i32,
b: bool, b: bool,
c: f32, c: f32,
}; };
fn testFoo(foo: StructFoo) !void {
try expect(foo.b);
}
fn testMutation(foo: *StructFoo) void {
foo.c = 100;
}
const Node = struct { const Node = struct {
val: Val, val: Val,
@ -84,7 +69,7 @@ test "struct byval assign" {
try expect(foo2.a == 1234); try expect(foo2.a == 1234);
} }
fn structInitializer() void { test "struct initializer" {
const val = Val{ .x = 42 }; const val = Val{ .x = 42 };
try expect(val.x == 42); try expect(val.x == 42);
} }