aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-25 15:06:47 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-25 15:11:21 -0700
commit8509e7111d80a07e778aa2a57d58d2bea6945014 (patch)
treee7eedaf980ada713a6c3d2da3e6153751d03bed6 /src/type.zig
parenta132190cad80669306705b72276e9641401426fb (diff)
downloadzig-8509e7111d80a07e778aa2a57d58d2bea6945014.tar.gz
zig-8509e7111d80a07e778aa2a57d58d2bea6945014.zip
stage2: fix switch on tagged union capture-by-pointer
* AstGen: always use `typeof` and never `typeof_elem` on the `switch_cond`/`switch_cond_ref` instruction because both variants return a value and not a pointer. - Delete the `typeof_elem` ZIR instruction since it is no longer needed. * Sema: validateUnionInit now recognizes a comptime mutable value and no longer emits a compile error saying "cannot evaluate constant expression" - Still to-do is detecting comptime union values in a function that is not being executed at compile-time. - This is still to-do for structs too. * Sema: when emitting a call AIR instruction, call resolveTypeLayout on all the parameter types as well as the return type. * `Type.structFieldOffset` now works for unions in addition to structs.
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig59
1 files changed, 37 insertions, 22 deletions
diff --git a/src/type.zig b/src/type.zig
index e77780d9ca..4682b3ed10 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -3391,34 +3391,49 @@ pub const Type = extern union {
}
}
+ /// Supports structs and unions.
pub fn structFieldOffset(ty: Type, index: usize, target: Target) u64 {
- const fields = ty.structFields();
- if (ty.castTag(.@"struct")) |payload| {
- const struct_obj = payload.data;
- assert(struct_obj.status == .have_layout);
- const is_packed = struct_obj.layout == .Packed;
- if (is_packed) @panic("TODO packed structs");
- }
+ switch (ty.tag()) {
+ .@"struct" => {
+ const struct_obj = ty.castTag(.@"struct").?.data;
+ assert(struct_obj.status == .have_layout);
+ const is_packed = struct_obj.layout == .Packed;
+ if (is_packed) @panic("TODO packed structs");
- var offset: u64 = 0;
- var big_align: u32 = 0;
- for (fields.values()) |field, i| {
- if (!field.ty.hasCodeGenBits()) continue;
+ var offset: u64 = 0;
+ var big_align: u32 = 0;
+ for (struct_obj.fields.values()) |field, i| {
+ if (!field.ty.hasCodeGenBits()) continue;
- const field_align = a: {
- if (field.abi_align.tag() == .abi_align_default) {
- break :a field.ty.abiAlignment(target);
+ const field_align = a: {
+ if (field.abi_align.tag() == .abi_align_default) {
+ break :a field.ty.abiAlignment(target);
+ } else {
+ break :a @intCast(u32, field.abi_align.toUnsignedInt());
+ }
+ };
+ big_align = @maximum(big_align, field_align);
+ offset = std.mem.alignForwardGeneric(u64, offset, field_align);
+ if (i == index) return offset;
+ offset += field.ty.abiSize(target);
+ }
+ offset = std.mem.alignForwardGeneric(u64, offset, big_align);
+ return offset;
+ },
+ .@"union" => return 0,
+ .union_tagged => {
+ const union_obj = ty.castTag(.union_tagged).?.data;
+ const layout = union_obj.getLayout(target, true);
+ if (layout.tag_align >= layout.payload_align) {
+ // {Tag, Payload}
+ return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
} else {
- break :a @intCast(u32, field.abi_align.toUnsignedInt());
+ // {Payload, Tag}
+ return 0;
}
- };
- big_align = @maximum(big_align, field_align);
- offset = std.mem.alignForwardGeneric(u64, offset, field_align);
- if (i == index) return offset;
- offset += field.ty.abiSize(target);
+ },
+ else => unreachable,
}
- offset = std.mem.alignForwardGeneric(u64, offset, big_align);
- return offset;
}
pub fn declSrcLoc(ty: Type) Module.SrcLoc {