aboutsummaryrefslogtreecommitdiff
path: root/src/type.zig
diff options
context:
space:
mode:
authorkcbanner <kcbanner@gmail.com>2023-10-21 12:03:36 -0400
committerMatthew Lugg <mlugg@mlugg.co.uk>2023-10-31 01:35:58 +0000
commit4d044ee7e0b1ca61b8f2205f318449780ae23bd2 (patch)
tree682b42b724238e7dc0231685eecaf0f408a1620e /src/type.zig
parentffaeb4533395fafcf020d0aca2f2efd58e48a384 (diff)
downloadzig-4d044ee7e0b1ca61b8f2205f318449780ae23bd2.tar.gz
zig-4d044ee7e0b1ca61b8f2205f318449780ae23bd2.zip
sema: Add union alignment resolution
- Add resolveUnionAlignment, to resolve a union's alignment only, without triggering layout resolution. - Update resolveUnionLayout to cache size, alignment, and padding. abiSizeAdvanced and abiAlignmentAdvanced now use this information instead of computing it each time.
Diffstat (limited to 'src/type.zig')
-rw-r--r--src/type.zig74
1 files changed, 14 insertions, 60 deletions
diff --git a/src/type.zig b/src/type.zig
index 086a293351..eef3783fe6 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -1034,66 +1034,20 @@ pub const Type = struct {
}
return .{ .scalar = big_align };
},
-
.union_type => |union_type| {
- if (opt_sema) |sema| {
- if (union_type.flagsPtr(ip).status == .field_types_wip) {
- // We'll guess "pointer-aligned", if the union has an
- // underaligned pointer field then some allocations
- // might require explicit alignment.
- return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) };
- }
- _ = try sema.resolveTypeFields(ty);
- }
- if (!union_type.haveFieldTypes(ip)) switch (strat) {
+ const flags = union_type.flagsPtr(ip).*;
+ if (flags.alignment != .none) return .{ .scalar = flags.alignment };
+
+ if (!union_type.haveLayout(ip)) switch (strat) {
.eager => unreachable, // union layout not resolved
- .sema => unreachable, // handled above
+ .sema => |sema| return .{ .scalar = try sema.resolveUnionAlignment(ty, union_type) },
.lazy => return .{ .val = (try mod.intern(.{ .int = .{
.ty = .comptime_int_type,
.storage = .{ .lazy_align = ty.toIntern() },
} })).toValue() },
};
- const union_obj = ip.loadUnionType(union_type);
- if (union_obj.field_names.len == 0) {
- if (union_obj.hasTag(ip)) {
- return abiAlignmentAdvanced(union_obj.enum_tag_ty.toType(), mod, strat);
- } else {
- return .{ .scalar = .@"1" };
- }
- }
- var max_align: Alignment = .@"1";
- if (union_obj.hasTag(ip)) max_align = union_obj.enum_tag_ty.toType().abiAlignment(mod);
- for (0..union_obj.field_names.len) |field_index| {
- const field_ty = union_obj.field_types.get(ip)[field_index].toType();
- const field_align = if (union_obj.field_aligns.len == 0)
- .none
- else
- union_obj.field_aligns.get(ip)[field_index];
- if (!(field_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
- error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
- .ty = .comptime_int_type,
- .storage = .{ .lazy_align = ty.toIntern() },
- } })).toValue() },
- else => |e| return e,
- })) continue;
-
- const field_align_bytes: Alignment = if (field_align != .none)
- field_align
- else switch (try field_ty.abiAlignmentAdvanced(mod, strat)) {
- .scalar => |a| a,
- .val => switch (strat) {
- .eager => unreachable, // struct layout not resolved
- .sema => unreachable, // handled above
- .lazy => return .{ .val = (try mod.intern(.{ .int = .{
- .ty = .comptime_int_type,
- .storage = .{ .lazy_align = ty.toIntern() },
- } })).toValue() },
- },
- };
- max_align = max_align.max(field_align_bytes);
- }
- return .{ .scalar = max_align };
+ return .{ .scalar = union_type.flagsPtr(ip).alignment };
},
.opaque_type => return .{ .scalar = .@"1" },
.enum_type => |enum_type| return .{
@@ -1451,8 +1405,8 @@ pub const Type = struct {
},
.eager => {},
}
- const union_obj = ip.loadUnionType(union_type);
- return AbiSizeAdvanced{ .scalar = mod.unionAbiSize(union_obj) };
+
+ return .{ .scalar = union_type.size(ip).* };
},
.opaque_type => unreachable, // no size available
.enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) },
@@ -2680,11 +2634,11 @@ pub const Type = struct {
if (struct_type.flagsPtr(ip).field_types_wip)
return false;
- try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type);
-
struct_type.flagsPtr(ip).requires_comptime = .wip;
errdefer struct_type.flagsPtr(ip).requires_comptime = .unknown;
+ try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type);
+
for (0..struct_type.field_types.len) |i_usize| {
const i: u32 = @intCast(i_usize);
if (struct_type.fieldIsComptime(ip, i)) continue;
@@ -2723,12 +2677,12 @@ pub const Type = struct {
if (union_type.flagsPtr(ip).status == .field_types_wip)
return false;
- try sema.resolveTypeFieldsUnion(ty, union_type);
- const union_obj = ip.loadUnionType(union_type);
+ union_type.flagsPtr(ip).requires_comptime = .wip;
+ errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;
- union_obj.flagsPtr(ip).requires_comptime = .wip;
- errdefer union_obj.flagsPtr(ip).requires_comptime = .unknown;
+ try sema.resolveTypeFieldsUnion(ty, union_type);
+ const union_obj = ip.loadUnionType(union_type);
for (0..union_obj.field_types.len) |field_idx| {
const field_ty = union_obj.field_types.get(ip)[field_idx];
if (try field_ty.toType().comptimeOnlyAdvanced(mod, opt_sema)) {