mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
compiler: represent captures directly in InternPool
These were previously associated with the type's namespace, but we need to store them directly in the InternPool for #18816.
This commit is contained in:
parent
975b859377
commit
8ec6f730ef
@ -501,6 +501,42 @@ pub const OptionalNullTerminatedString = enum(u32) {
|
||||
}
|
||||
};
|
||||
|
||||
/// A single value captured in the closure of a namespace type. This is not a plain
|
||||
/// `Index` because we must differentiate between runtime-known values (where we
|
||||
/// store the type) and comptime-known values (where we store the value).
|
||||
pub const CaptureValue = packed struct(u32) {
|
||||
tag: enum { @"comptime", runtime },
|
||||
idx: u31,
|
||||
|
||||
pub fn wrap(val: Unwrapped) CaptureValue {
|
||||
return switch (val) {
|
||||
.@"comptime" => |i| .{ .tag = .@"comptime", .idx = @intCast(@intFromEnum(i)) },
|
||||
.runtime => |i| .{ .tag = .runtime, .idx = @intCast(@intFromEnum(i)) },
|
||||
};
|
||||
}
|
||||
pub fn unwrap(val: CaptureValue) Unwrapped {
|
||||
return switch (val.tag) {
|
||||
.@"comptime" => .{ .@"comptime" = @enumFromInt(val.idx) },
|
||||
.runtime => .{ .runtime = @enumFromInt(val.idx) },
|
||||
};
|
||||
}
|
||||
|
||||
pub const Unwrapped = union(enum) {
|
||||
/// Index refers to the value.
|
||||
@"comptime": Index,
|
||||
/// Index refers to the type.
|
||||
runtime: Index,
|
||||
};
|
||||
|
||||
pub const Slice = struct {
|
||||
start: u32,
|
||||
len: u32,
|
||||
pub fn get(slice: Slice, ip: *const InternPool) []CaptureValue {
|
||||
return @ptrCast(ip.extra.items[slice.start..][0..slice.len]);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
pub const Key = union(enum) {
|
||||
int_type: IntType,
|
||||
ptr_type: PtrType,
|
||||
@ -707,6 +743,7 @@ pub const Key = union(enum) {
|
||||
/// This may be updated via `setTagType` later.
|
||||
tag_ty: Index = .none,
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
captures: []const CaptureValue,
|
||||
|
||||
pub fn toEnumType(self: @This()) LoadedEnumType {
|
||||
if (true) @compileError("AHHHH");
|
||||
@ -1660,6 +1697,7 @@ pub const LoadedUnionType = struct {
|
||||
field_aligns: Alignment.Slice,
|
||||
/// Index of the union_decl ZIR instruction.
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
captures: CaptureValue.Slice,
|
||||
|
||||
pub const RuntimeTag = enum(u2) {
|
||||
none,
|
||||
@ -1791,24 +1829,47 @@ pub const LoadedUnionType = struct {
|
||||
};
|
||||
|
||||
pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
|
||||
const extra_index = ip.items.items(.data)[@intFromEnum(index)];
|
||||
const type_union = ip.extraDataTrail(Tag.TypeUnion, extra_index);
|
||||
const data = ip.items.items(.data)[@intFromEnum(index)];
|
||||
const type_union = ip.extraDataTrail(Tag.TypeUnion, data);
|
||||
const fields_len = type_union.data.fields_len;
|
||||
|
||||
var extra_index = type_union.end;
|
||||
const captures_len = if (type_union.data.flags.any_captures) c: {
|
||||
const len = ip.extra.items[extra_index];
|
||||
extra_index += 1;
|
||||
break :c len;
|
||||
} else 0;
|
||||
|
||||
const captures: CaptureValue.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = captures_len,
|
||||
};
|
||||
extra_index += captures_len;
|
||||
|
||||
const field_types: Index.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = fields_len,
|
||||
};
|
||||
extra_index += fields_len;
|
||||
|
||||
const field_aligns: Alignment.Slice = if (type_union.data.flags.any_aligned_fields) a: {
|
||||
const a: Alignment.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = fields_len,
|
||||
};
|
||||
extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable;
|
||||
break :a a;
|
||||
} else .{ .start = 0, .len = 0 };
|
||||
|
||||
return .{
|
||||
.extra_index = extra_index,
|
||||
.extra_index = data,
|
||||
.decl = type_union.data.decl,
|
||||
.namespace = type_union.data.namespace,
|
||||
.enum_tag_ty = type_union.data.tag_ty,
|
||||
.field_types = .{
|
||||
.start = type_union.end,
|
||||
.len = fields_len,
|
||||
},
|
||||
.field_aligns = .{
|
||||
.start = type_union.end + fields_len,
|
||||
.len = if (type_union.data.flags.any_aligned_fields) fields_len else 0,
|
||||
},
|
||||
.field_types = field_types,
|
||||
.field_aligns = field_aligns,
|
||||
.zir_index = type_union.data.zir_index,
|
||||
.captures = captures,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1830,6 +1891,7 @@ pub const LoadedStructType = struct {
|
||||
comptime_bits: ComptimeBits,
|
||||
offsets: Offsets,
|
||||
names_map: OptionalMapIndex,
|
||||
captures: CaptureValue.Slice,
|
||||
|
||||
pub const ComptimeBits = struct {
|
||||
start: u32,
|
||||
@ -2162,10 +2224,26 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
|
||||
.comptime_bits = .{ .start = 0, .len = 0 },
|
||||
.offsets = .{ .start = 0, .len = 0 },
|
||||
.names_map = .none,
|
||||
.captures = .{ .start = 0, .len = 0 },
|
||||
};
|
||||
const extra = ip.extraDataTrail(Tag.TypeStruct, item.data);
|
||||
const fields_len = extra.data.fields_len;
|
||||
var extra_index = extra.end + fields_len; // skip field types
|
||||
var extra_index = extra.end;
|
||||
const captures_len = if (extra.data.flags.any_captures) c: {
|
||||
const len = ip.extra.items[extra_index];
|
||||
extra_index += 1;
|
||||
break :c len;
|
||||
} else 0;
|
||||
const captures: CaptureValue.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = captures_len,
|
||||
};
|
||||
extra_index += captures_len;
|
||||
const field_types: Index.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = fields_len,
|
||||
};
|
||||
extra_index += fields_len;
|
||||
const names_map: OptionalMapIndex, const names: NullTerminatedString.Slice = if (!extra.data.flags.is_tuple) n: {
|
||||
const names_map: OptionalMapIndex = @enumFromInt(ip.extra.items[extra_index]);
|
||||
extra_index += 1;
|
||||
@ -2211,42 +2289,64 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
|
||||
.zir_index = extra.data.zir_index,
|
||||
.layout = if (extra.data.flags.is_extern) .Extern else .Auto,
|
||||
.field_names = names,
|
||||
.field_types = .{ .start = extra.end, .len = fields_len },
|
||||
.field_types = field_types,
|
||||
.field_inits = inits,
|
||||
.field_aligns = aligns,
|
||||
.runtime_order = runtime_order,
|
||||
.comptime_bits = comptime_bits,
|
||||
.offsets = offsets,
|
||||
.names_map = names_map,
|
||||
.captures = captures,
|
||||
};
|
||||
},
|
||||
.type_struct_packed, .type_struct_packed_inits => {
|
||||
const extra = ip.extraDataTrail(Tag.TypeStructPacked, item.data);
|
||||
const has_inits = item.tag == .type_struct_packed_inits;
|
||||
const fields_len = extra.data.fields_len;
|
||||
var extra_index = extra.end;
|
||||
const captures_len = if (extra.data.flags.any_captures) c: {
|
||||
const len = ip.extra.items[extra_index];
|
||||
extra_index += 1;
|
||||
break :c len;
|
||||
} else 0;
|
||||
const captures: CaptureValue.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = captures_len,
|
||||
};
|
||||
extra_index += captures_len;
|
||||
const field_types: Index.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = fields_len,
|
||||
};
|
||||
extra_index += fields_len;
|
||||
const field_names: NullTerminatedString.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = fields_len,
|
||||
};
|
||||
extra_index += fields_len;
|
||||
const field_inits: Index.Slice = if (has_inits) inits: {
|
||||
const i: Index.Slice = .{
|
||||
.start = extra_index,
|
||||
.len = fields_len,
|
||||
};
|
||||
extra_index += fields_len;
|
||||
break :inits i;
|
||||
} else .{ .start = 0, .len = 0 };
|
||||
return .{
|
||||
.extra_index = item.data,
|
||||
.decl = extra.data.decl.toOptional(),
|
||||
.namespace = extra.data.namespace,
|
||||
.zir_index = extra.data.zir_index,
|
||||
.layout = .Packed,
|
||||
.field_names = .{
|
||||
.start = extra.end + fields_len,
|
||||
.len = fields_len,
|
||||
},
|
||||
.field_types = .{
|
||||
.start = extra.end,
|
||||
.len = fields_len,
|
||||
},
|
||||
.field_inits = if (has_inits) .{
|
||||
.start = extra.end + 2 * fields_len,
|
||||
.len = fields_len,
|
||||
} else .{ .start = 0, .len = 0 },
|
||||
.field_names = field_names,
|
||||
.field_types = field_types,
|
||||
.field_inits = field_inits,
|
||||
.field_aligns = .{ .start = 0, .len = 0 },
|
||||
.runtime_order = .{ .start = 0, .len = 0 },
|
||||
.comptime_bits = .{ .start = 0, .len = 0 },
|
||||
.offsets = .{ .start = 0, .len = 0 },
|
||||
.names_map = extra.data.names_map.toOptional(),
|
||||
.captures = captures,
|
||||
};
|
||||
},
|
||||
else => unreachable,
|
||||
@ -2273,6 +2373,7 @@ const LoadedEnumType = struct {
|
||||
/// This is guaranteed to not be `.none` if explicit values are provided.
|
||||
values_map: OptionalMapIndex,
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
captures: CaptureValue.Slice,
|
||||
|
||||
pub const TagMode = enum {
|
||||
/// The integer tag type was auto-numbered by zig.
|
||||
@ -2332,7 +2433,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
|
||||
.namespace = extra.data.namespace,
|
||||
.tag_ty = extra.data.int_tag_type,
|
||||
.names = .{
|
||||
.start = @intCast(extra.end),
|
||||
.start = @intCast(extra.end + extra.data.captures_len),
|
||||
.len = extra.data.fields_len,
|
||||
},
|
||||
.values = .{ .start = 0, .len = 0 },
|
||||
@ -2340,6 +2441,10 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
|
||||
.names_map = extra.data.names_map,
|
||||
.values_map = .none,
|
||||
.zir_index = extra.data.zir_index,
|
||||
.captures = .{
|
||||
.start = @intCast(extra.end),
|
||||
.len = extra.data.captures_len,
|
||||
},
|
||||
};
|
||||
},
|
||||
.type_enum_explicit, .type_enum_nonexhaustive => {
|
||||
@ -2349,11 +2454,11 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
|
||||
.namespace = extra.data.namespace,
|
||||
.tag_ty = extra.data.int_tag_type,
|
||||
.names = .{
|
||||
.start = @intCast(extra.end),
|
||||
.start = @intCast(extra.end + extra.data.captures_len),
|
||||
.len = extra.data.fields_len,
|
||||
},
|
||||
.values = .{
|
||||
.start = @intCast(extra.end + extra.data.fields_len),
|
||||
.start = @intCast(extra.end + extra.data.captures_len + extra.data.fields_len),
|
||||
.len = if (extra.data.values_map != .none) extra.data.fields_len else 0,
|
||||
},
|
||||
.tag_mode = switch (item.tag) {
|
||||
@ -2364,6 +2469,10 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
|
||||
.names_map = extra.data.names_map,
|
||||
.values_map = extra.data.values_map,
|
||||
.zir_index = extra.data.zir_index,
|
||||
.captures = .{
|
||||
.start = @intCast(extra.end),
|
||||
.len = extra.data.captures_len,
|
||||
},
|
||||
};
|
||||
},
|
||||
else => unreachable,
|
||||
@ -2378,12 +2487,22 @@ pub const LoadedOpaqueType = struct {
|
||||
namespace: NamespaceIndex,
|
||||
/// The index of the `opaque_decl` instruction.
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
captures: CaptureValue.Slice,
|
||||
};
|
||||
|
||||
pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType {
|
||||
assert(ip.items.items(.tag)[@intFromEnum(index)] == .type_opaque);
|
||||
const extra_index = ip.items.items(.data)[@intFromEnum(index)];
|
||||
return ip.extraData(LoadedOpaqueType, extra_index);
|
||||
const extra = ip.extraDataTrail(Tag.TypeOpaque, extra_index);
|
||||
return .{
|
||||
.decl = extra.data.decl,
|
||||
.namespace = extra.data.namespace,
|
||||
.zir_index = extra.data.zir_index,
|
||||
.captures = .{
|
||||
.start = extra.end,
|
||||
.len = extra.data.captures_len,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub const Item = struct {
|
||||
@ -2601,7 +2720,7 @@ pub const Index = enum(u32) {
|
||||
type_enum_explicit: DataIsExtraIndexOfEnumExplicit,
|
||||
type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit,
|
||||
simple_type: struct { data: SimpleType },
|
||||
type_opaque: struct { data: *Key.OpaqueType },
|
||||
type_opaque: struct { data: *Tag.TypeOpaque },
|
||||
type_struct: struct { data: *Tag.TypeStruct },
|
||||
type_struct_anon: DataIsExtraIndexOfTypeStructAnon,
|
||||
type_struct_packed: struct { data: *Tag.TypeStructPacked },
|
||||
@ -3036,7 +3155,7 @@ pub const Tag = enum(u8) {
|
||||
/// data is SimpleType enum value.
|
||||
simple_type,
|
||||
/// An opaque type.
|
||||
/// data is index of Key.OpaqueType in extra.
|
||||
/// data is index of Tag.TypeOpaque in extra.
|
||||
type_opaque,
|
||||
/// A non-packed struct type.
|
||||
/// data is 0 or extra index of `TypeStruct`.
|
||||
@ -3239,7 +3358,6 @@ pub const Tag = enum(u8) {
|
||||
memoized_call,
|
||||
|
||||
const ErrorUnionType = Key.ErrorUnionType;
|
||||
const OpaqueType = LoadedOpaqueType;
|
||||
const TypeValue = Key.TypeValue;
|
||||
const Error = Key.Error;
|
||||
const EnumTag = Key.EnumTag;
|
||||
@ -3266,7 +3384,7 @@ pub const Tag = enum(u8) {
|
||||
.type_enum_explicit => EnumExplicit,
|
||||
.type_enum_nonexhaustive => EnumExplicit,
|
||||
.simple_type => unreachable,
|
||||
.type_opaque => OpaqueType,
|
||||
.type_opaque => TypeOpaque,
|
||||
.type_struct => TypeStruct,
|
||||
.type_struct_anon => TypeStructAnon,
|
||||
.type_struct_packed, .type_struct_packed_inits => TypeStructPacked,
|
||||
@ -3424,8 +3542,10 @@ pub const Tag = enum(u8) {
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. field type: Index for each field; declaration order
|
||||
/// 1. field align: Alignment for each field; declaration order
|
||||
/// 0. captures_len: u32 // if `any_captures`
|
||||
/// 1. capture: CaptureValue // for each `captures_len`
|
||||
/// 2. field type: Index for each field; declaration order
|
||||
/// 3. field align: Alignment for each field; declaration order
|
||||
pub const TypeUnion = struct {
|
||||
flags: Flags,
|
||||
/// This could be provided through the tag type, but it is more convenient
|
||||
@ -3443,6 +3563,7 @@ pub const Tag = enum(u8) {
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
any_captures: bool,
|
||||
runtime_tag: LoadedUnionType.RuntimeTag,
|
||||
/// If false, the field alignment trailing data is omitted.
|
||||
any_aligned_fields: bool,
|
||||
@ -3452,14 +3573,16 @@ pub const Tag = enum(u8) {
|
||||
assumed_runtime_bits: bool,
|
||||
assumed_pointer_aligned: bool,
|
||||
alignment: Alignment,
|
||||
_: u14 = 0,
|
||||
_: u13 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. type: Index for each fields_len
|
||||
/// 1. name: NullTerminatedString for each fields_len
|
||||
/// 2. init: Index for each fields_len // if tag is type_struct_packed_inits
|
||||
/// 0. captures_len: u32 // if `any_captures`
|
||||
/// 1. capture: CaptureValue // for each `captures_len`
|
||||
/// 2. type: Index for each fields_len
|
||||
/// 3. name: NullTerminatedString for each fields_len
|
||||
/// 4. init: Index for each fields_len // if tag is type_struct_packed_inits
|
||||
pub const TypeStructPacked = struct {
|
||||
decl: DeclIndex,
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
@ -3470,10 +3593,11 @@ pub const Tag = enum(u8) {
|
||||
flags: Flags,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
any_captures: bool,
|
||||
/// Dependency loop detection when resolving field inits.
|
||||
field_inits_wip: bool,
|
||||
inits_resolved: bool,
|
||||
_: u30 = 0,
|
||||
_: u29 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
@ -3492,21 +3616,23 @@ pub const Tag = enum(u8) {
|
||||
/// than coming up with some other scheme for the data.
|
||||
///
|
||||
/// Trailing:
|
||||
/// 0. type: Index for each field in declared order
|
||||
/// 1. if not is_tuple:
|
||||
/// 0. captures_len: u32 // if `any_captures`
|
||||
/// 1. capture: CaptureValue // for each `captures_len`
|
||||
/// 2. type: Index for each field in declared order
|
||||
/// 3. if not is_tuple:
|
||||
/// names_map: MapIndex,
|
||||
/// name: NullTerminatedString // for each field in declared order
|
||||
/// 2. if any_default_inits:
|
||||
/// 4. if any_default_inits:
|
||||
/// init: Index // for each field in declared order
|
||||
/// 3. if has_namespace:
|
||||
/// 5. if has_namespace:
|
||||
/// namespace: NamespaceIndex
|
||||
/// 4. if any_aligned_fields:
|
||||
/// 6. if any_aligned_fields:
|
||||
/// align: Alignment // for each field in declared order
|
||||
/// 5. if any_comptime_fields:
|
||||
/// 7. if any_comptime_fields:
|
||||
/// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0
|
||||
/// 6. if not is_extern:
|
||||
/// 8. if not is_extern:
|
||||
/// field_index: RuntimeOrder // for each field in runtime order
|
||||
/// 7. field_offset: u32 // for each field in declared order, undef until layout_resolved
|
||||
/// 9. field_offset: u32 // for each field in declared order, undef until layout_resolved
|
||||
pub const TypeStruct = struct {
|
||||
decl: DeclIndex,
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
@ -3515,6 +3641,7 @@ pub const Tag = enum(u8) {
|
||||
size: u32,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
any_captures: bool,
|
||||
is_extern: bool,
|
||||
known_non_opv: bool,
|
||||
requires_comptime: RequiresComptime,
|
||||
@ -3544,9 +3671,21 @@ pub const Tag = enum(u8) {
|
||||
// which `layout_resolved` does not ensure.
|
||||
fully_resolved: bool,
|
||||
|
||||
_: u8 = 0,
|
||||
_: u7 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. capture: CaptureValue // for each `captures_len`
|
||||
pub const TypeOpaque = struct {
|
||||
/// The opaque's owner Decl.
|
||||
decl: DeclIndex,
|
||||
/// Contains the declarations inside this opaque.
|
||||
namespace: NamespaceIndex,
|
||||
/// The index of the `opaque_decl` instruction.
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
captures_len: u32,
|
||||
};
|
||||
};
|
||||
|
||||
/// State that is mutable during semantic analysis. This data is not used for
|
||||
@ -3853,11 +3992,13 @@ pub const Array = struct {
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. field name: NullTerminatedString for each fields_len; declaration order
|
||||
/// 1. tag value: Index for each fields_len; declaration order
|
||||
/// 0. capture: CaptureValue // for each `captures_len`
|
||||
/// 1. field name: NullTerminatedString for each fields_len; declaration order
|
||||
/// 2. tag value: Index for each fields_len; declaration order
|
||||
pub const EnumExplicit = struct {
|
||||
/// The Decl that corresponds to the enum itself.
|
||||
decl: DeclIndex,
|
||||
captures_len: u32,
|
||||
/// This may be `none` if there are no declarations.
|
||||
namespace: OptionalNamespaceIndex,
|
||||
/// An integer type which is used for the numerical value of the enum, which
|
||||
@ -3874,10 +4015,12 @@ pub const EnumExplicit = struct {
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// 0. field name: NullTerminatedString for each fields_len; declaration order
|
||||
/// 0. capture: CaptureValue // for each `captures_len`
|
||||
/// 1. field name: NullTerminatedString for each fields_len; declaration order
|
||||
pub const EnumAuto = struct {
|
||||
/// The Decl that corresponds to the enum itself.
|
||||
decl: DeclIndex,
|
||||
captures_len: u32,
|
||||
/// This may be `none` if there are no declarations.
|
||||
namespace: OptionalNamespaceIndex,
|
||||
/// An integer type which is used for the numerical value of the enum, which
|
||||
@ -4187,7 +4330,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
|
||||
.inferred_error_set_type = @enumFromInt(data),
|
||||
},
|
||||
|
||||
.type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
|
||||
.type_opaque => .{ .opaque_type = .{
|
||||
.decl = ip.extraData(Tag.TypeOpaque, data).decl,
|
||||
} },
|
||||
|
||||
.type_struct => .{ .struct_type = if (data == 0) .{
|
||||
.decl = .none,
|
||||
@ -5497,7 +5642,16 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
}
|
||||
|
||||
pub const UnionTypeInit = struct {
|
||||
flags: Tag.TypeUnion.Flags,
|
||||
flags: packed struct {
|
||||
runtime_tag: LoadedUnionType.RuntimeTag,
|
||||
any_aligned_fields: bool,
|
||||
layout: std.builtin.Type.ContainerLayout,
|
||||
status: LoadedUnionType.Status,
|
||||
requires_comptime: RequiresComptime,
|
||||
assumed_runtime_bits: bool,
|
||||
assumed_pointer_aligned: bool,
|
||||
alignment: Alignment,
|
||||
},
|
||||
decl: DeclIndex,
|
||||
namespace: NamespaceIndex,
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
@ -5509,6 +5663,7 @@ pub const UnionTypeInit = struct {
|
||||
/// The logic for `any_aligned_fields` is asserted to have been done before
|
||||
/// calling this function.
|
||||
field_aligns: []const Alignment,
|
||||
captures: []const CaptureValue,
|
||||
};
|
||||
|
||||
pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocator.Error!Index {
|
||||
@ -5516,12 +5671,24 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
|
||||
const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0;
|
||||
const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4);
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeUnion).Struct.fields.len +
|
||||
@intFromBool(ini.captures.len != 0) + // captures_len
|
||||
ini.captures.len + // captures
|
||||
ini.fields_len + // field types
|
||||
align_elements_len);
|
||||
try ip.items.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const union_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeUnion{
|
||||
.flags = ini.flags,
|
||||
.flags = .{
|
||||
.any_captures = ini.captures.len != 0,
|
||||
.runtime_tag = ini.flags.runtime_tag,
|
||||
.any_aligned_fields = ini.flags.any_aligned_fields,
|
||||
.layout = ini.flags.layout,
|
||||
.status = ini.flags.status,
|
||||
.requires_comptime = ini.flags.requires_comptime,
|
||||
.assumed_runtime_bits = ini.flags.assumed_runtime_bits,
|
||||
.assumed_pointer_aligned = ini.flags.assumed_pointer_aligned,
|
||||
.alignment = ini.flags.alignment,
|
||||
},
|
||||
.fields_len = ini.fields_len,
|
||||
.size = std.math.maxInt(u32),
|
||||
.padding = std.math.maxInt(u32),
|
||||
@ -5531,6 +5698,11 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, ini: UnionTypeInit) Allocat
|
||||
.zir_index = ini.zir_index,
|
||||
});
|
||||
|
||||
if (ini.captures.len != 0) {
|
||||
ip.extra.appendAssumeCapacity(@intCast(ini.captures.len));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
|
||||
}
|
||||
|
||||
// field types
|
||||
if (ini.field_types.len > 0) {
|
||||
assert(ini.field_types.len == ini.fields_len);
|
||||
@ -5582,6 +5754,7 @@ pub const StructTypeInit = struct {
|
||||
any_default_inits: bool,
|
||||
inits_resolved: bool,
|
||||
any_aligned_fields: bool,
|
||||
captures: []const CaptureValue,
|
||||
};
|
||||
|
||||
pub fn getStructType(
|
||||
@ -5605,6 +5778,8 @@ pub fn getStructType(
|
||||
.Extern => true,
|
||||
.Packed => {
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeStructPacked).Struct.fields.len +
|
||||
@intFromBool(ini.captures.len != 0) + // captures_len
|
||||
ini.captures.len + // captures
|
||||
ini.fields_len + // types
|
||||
ini.fields_len + // names
|
||||
ini.fields_len); // inits
|
||||
@ -5618,11 +5793,16 @@ pub fn getStructType(
|
||||
.backing_int_ty = .none,
|
||||
.names_map = names_map,
|
||||
.flags = .{
|
||||
.any_captures = ini.captures.len != 0,
|
||||
.field_inits_wip = false,
|
||||
.inits_resolved = ini.inits_resolved,
|
||||
},
|
||||
}),
|
||||
});
|
||||
if (ini.captures.len != 0) {
|
||||
ip.extra.appendAssumeCapacity(@intCast(ini.captures.len));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
|
||||
}
|
||||
ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len);
|
||||
ip.extra.appendNTimesAssumeCapacity(@intFromEnum(OptionalNullTerminatedString.none), ini.fields_len);
|
||||
if (ini.any_default_inits) {
|
||||
@ -5637,6 +5817,8 @@ pub fn getStructType(
|
||||
const comptime_elements_len = if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0;
|
||||
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeStruct).Struct.fields.len +
|
||||
@intFromBool(ini.captures.len != 0) + // captures_len
|
||||
ini.captures.len + // captures
|
||||
(ini.fields_len * 5) + // types, names, inits, runtime order, offsets
|
||||
align_elements_len + comptime_elements_len +
|
||||
2); // names_map + namespace
|
||||
@ -5648,6 +5830,7 @@ pub fn getStructType(
|
||||
.fields_len = ini.fields_len,
|
||||
.size = std.math.maxInt(u32),
|
||||
.flags = .{
|
||||
.any_captures = ini.captures.len != 0,
|
||||
.is_extern = is_extern,
|
||||
.known_non_opv = ini.known_non_opv,
|
||||
.requires_comptime = ini.requires_comptime,
|
||||
@ -5669,6 +5852,10 @@ pub fn getStructType(
|
||||
},
|
||||
}),
|
||||
});
|
||||
if (ini.captures.len != 0) {
|
||||
ip.extra.appendAssumeCapacity(@intCast(ini.captures.len));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
|
||||
}
|
||||
ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), ini.fields_len);
|
||||
if (!ini.is_tuple) {
|
||||
ip.extra.appendAssumeCapacity(@intFromEnum(names_map));
|
||||
@ -6405,11 +6592,12 @@ fn getIncompleteEnumAuto(
|
||||
const names_map = try ip.addMap(gpa, enum_type.fields_len);
|
||||
|
||||
const extra_fields_len: u32 = @typeInfo(EnumAuto).Struct.fields.len;
|
||||
try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len);
|
||||
try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.captures.len + enum_type.fields_len);
|
||||
try ip.items.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const extra_index = ip.addExtraAssumeCapacity(EnumAuto{
|
||||
.decl = enum_type.decl,
|
||||
.captures_len = @intCast(enum_type.captures.len),
|
||||
.namespace = enum_type.namespace,
|
||||
.int_tag_type = int_tag_type,
|
||||
.names_map = names_map,
|
||||
@ -6421,6 +6609,7 @@ fn getIncompleteEnumAuto(
|
||||
.tag = .type_enum_auto,
|
||||
.data = extra_index,
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.captures));
|
||||
ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), enum_type.fields_len);
|
||||
return .{
|
||||
.index = @enumFromInt(ip.items.len - 1),
|
||||
@ -6455,11 +6644,12 @@ fn getIncompleteEnumExplicit(
|
||||
if (enum_type.has_values) enum_type.fields_len else 0;
|
||||
|
||||
const extra_fields_len: u32 = @typeInfo(EnumExplicit).Struct.fields.len;
|
||||
try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + reserved_len);
|
||||
try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.captures.len + reserved_len);
|
||||
try ip.items.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const extra_index = ip.addExtraAssumeCapacity(EnumExplicit{
|
||||
.decl = enum_type.decl,
|
||||
.captures_len = @intCast(enum_type.captures.len),
|
||||
.namespace = enum_type.namespace,
|
||||
.int_tag_type = enum_type.tag_ty,
|
||||
.fields_len = enum_type.fields_len,
|
||||
@ -6472,6 +6662,7 @@ fn getIncompleteEnumExplicit(
|
||||
.tag = tag,
|
||||
.data = extra_index,
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.captures));
|
||||
// This is both fields and values (if present).
|
||||
ip.extra.appendNTimesAssumeCapacity(@intFromEnum(Index.none), reserved_len);
|
||||
return .{
|
||||
@ -6492,6 +6683,7 @@ pub const GetEnumInit = struct {
|
||||
values: []const Index,
|
||||
tag_mode: LoadedEnumType.TagMode,
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
captures: []const CaptureValue,
|
||||
};
|
||||
|
||||
pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Error!Index {
|
||||
@ -6513,11 +6705,12 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro
|
||||
|
||||
const fields_len: u32 = @intCast(ini.names.len);
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len +
|
||||
fields_len);
|
||||
ini.captures.len + fields_len);
|
||||
ip.items.appendAssumeCapacity(.{
|
||||
.tag = .type_enum_auto,
|
||||
.data = ip.addExtraAssumeCapacity(EnumAuto{
|
||||
.decl = ini.decl,
|
||||
.captures_len = @intCast(ini.captures.len),
|
||||
.namespace = ini.namespace,
|
||||
.int_tag_type = ini.tag_ty,
|
||||
.names_map = names_map,
|
||||
@ -6525,6 +6718,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro
|
||||
.zir_index = ini.zir_index,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
},
|
||||
@ -6533,7 +6727,7 @@ pub fn getEnum(ip: *InternPool, gpa: Allocator, ini: GetEnumInit) Allocator.Erro
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finishGetEnum(
|
||||
fn finishGetEnum(
|
||||
ip: *InternPool,
|
||||
gpa: Allocator,
|
||||
ini: GetEnumInit,
|
||||
@ -6549,11 +6743,12 @@ pub fn finishGetEnum(
|
||||
};
|
||||
const fields_len: u32 = @intCast(ini.names.len);
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len +
|
||||
fields_len);
|
||||
ini.captures.len + fields_len);
|
||||
ip.items.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = ip.addExtraAssumeCapacity(EnumExplicit{
|
||||
.decl = ini.decl,
|
||||
.captures_len = @intCast(ini.captures.len),
|
||||
.namespace = ini.namespace,
|
||||
.int_tag_type = ini.tag_ty,
|
||||
.fields_len = fields_len,
|
||||
@ -6562,23 +6757,37 @@ pub fn finishGetEnum(
|
||||
.zir_index = ini.zir_index,
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.names));
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.values));
|
||||
return @enumFromInt(ip.items.len - 1);
|
||||
}
|
||||
|
||||
pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, key: LoadedOpaqueType) Allocator.Error!Index {
|
||||
pub const OpaqueTypeIni = struct {
|
||||
decl: DeclIndex,
|
||||
namespace: NamespaceIndex,
|
||||
zir_index: TrackedInst.Index.Optional,
|
||||
captures: []const CaptureValue,
|
||||
};
|
||||
|
||||
pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, ini: OpaqueTypeIni) Allocator.Error!Index {
|
||||
const adapter: KeyAdapter = .{ .intern_pool = ip };
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(LoadedOpaqueType).Struct.fields.len);
|
||||
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(LoadedOpaqueType).Struct.fields.len + ini.captures.len);
|
||||
try ip.items.ensureUnusedCapacity(gpa, 1);
|
||||
const gop = try ip.map.getOrPutAdapted(gpa, Key{
|
||||
.opaque_type = .{ .decl = key.decl },
|
||||
.opaque_type = .{ .decl = ini.decl },
|
||||
}, adapter);
|
||||
if (gop.found_existing) return @enumFromInt(gop.index);
|
||||
ip.items.appendAssumeCapacity(.{
|
||||
.tag = .type_opaque,
|
||||
.data = ip.addExtraAssumeCapacity(key),
|
||||
.data = ip.addExtraAssumeCapacity(Tag.TypeOpaque{
|
||||
.decl = ini.decl,
|
||||
.namespace = ini.namespace,
|
||||
.zir_index = ini.zir_index,
|
||||
.captures_len = @intCast(ini.captures.len),
|
||||
}),
|
||||
});
|
||||
ip.extra.appendSliceAssumeCapacity(@ptrCast(ini.captures));
|
||||
return @enumFromInt(gop.index);
|
||||
}
|
||||
|
||||
@ -7442,12 +7651,31 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
|
||||
break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len);
|
||||
},
|
||||
.type_inferred_error_set => 0,
|
||||
.type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
|
||||
.type_enum_auto => @sizeOf(EnumAuto),
|
||||
.type_opaque => @sizeOf(Key.OpaqueType),
|
||||
.type_enum_explicit, .type_enum_nonexhaustive => b: {
|
||||
const info = ip.extraData(EnumExplicit, data);
|
||||
var ints = @typeInfo(EnumExplicit).Struct.fields.len + info.captures_len + info.fields_len;
|
||||
if (info.values_map != .none) ints += info.fields_len;
|
||||
break :b @sizeOf(u32) * ints;
|
||||
},
|
||||
.type_enum_auto => b: {
|
||||
const info = ip.extraData(EnumAuto, data);
|
||||
const ints = @typeInfo(EnumAuto).Struct.fields.len + info.captures_len + info.fields_len;
|
||||
break :b @sizeOf(u32) * ints;
|
||||
},
|
||||
.type_opaque => b: {
|
||||
const info = ip.extraData(Tag.TypeOpaque, data);
|
||||
const ints = @typeInfo(Tag.TypeOpaque).Struct.fields.len + info.captures_len;
|
||||
break :b @sizeOf(u32) * ints;
|
||||
},
|
||||
.type_struct => b: {
|
||||
const info = ip.extraData(Tag.TypeStruct, data);
|
||||
if (data == 0) break :b 0;
|
||||
const extra = ip.extraDataTrail(Tag.TypeStruct, data);
|
||||
const info = extra.data;
|
||||
var ints: usize = @typeInfo(Tag.TypeStruct).Struct.fields.len;
|
||||
if (info.flags.any_captures) {
|
||||
const captures_len = ip.extra.items[extra.end];
|
||||
ints += 1 + captures_len;
|
||||
}
|
||||
ints += info.fields_len; // types
|
||||
if (!info.flags.is_tuple) {
|
||||
ints += 1; // names_map
|
||||
@ -7470,14 +7698,24 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
|
||||
break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);
|
||||
},
|
||||
.type_struct_packed => b: {
|
||||
const info = ip.extraData(Tag.TypeStructPacked, data);
|
||||
const extra = ip.extraDataTrail(Tag.TypeStructPacked, data);
|
||||
const captures_len = if (extra.data.flags.any_captures)
|
||||
ip.extra.items[extra.end]
|
||||
else
|
||||
0;
|
||||
break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).Struct.fields.len +
|
||||
info.fields_len + info.fields_len);
|
||||
@intFromBool(extra.data.flags.any_captures) + captures_len +
|
||||
extra.data.fields_len * 2);
|
||||
},
|
||||
.type_struct_packed_inits => b: {
|
||||
const info = ip.extraData(Tag.TypeStructPacked, data);
|
||||
const extra = ip.extraDataTrail(Tag.TypeStructPacked, data);
|
||||
const captures_len = if (extra.data.flags.any_captures)
|
||||
ip.extra.items[extra.end]
|
||||
else
|
||||
0;
|
||||
break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).Struct.fields.len +
|
||||
info.fields_len + info.fields_len + info.fields_len);
|
||||
@intFromBool(extra.data.flags.any_captures) + captures_len +
|
||||
extra.data.fields_len * 3);
|
||||
},
|
||||
.type_tuple_anon => b: {
|
||||
const info = ip.extraData(TypeStructAnon, data);
|
||||
@ -7485,16 +7723,20 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
|
||||
},
|
||||
|
||||
.type_union => b: {
|
||||
const info = ip.extraData(Tag.TypeUnion, data);
|
||||
const enum_info = ip.loadEnumType(info.tag_ty);
|
||||
const fields_len: u32 = @intCast(enum_info.names.len);
|
||||
const per_field = @sizeOf(u32); // field type
|
||||
// 1 byte per field for alignment, rounded up to the nearest 4 bytes
|
||||
const alignments = if (info.flags.any_aligned_fields)
|
||||
((fields_len + 3) / 4) * 4
|
||||
const extra = ip.extraDataTrail(Tag.TypeUnion, data);
|
||||
const captures_len = if (extra.data.flags.any_captures)
|
||||
ip.extra.items[extra.end]
|
||||
else
|
||||
0;
|
||||
break :b @sizeOf(Tag.TypeUnion) + (fields_len * per_field) + alignments;
|
||||
const per_field = @sizeOf(u32); // field type
|
||||
// 1 byte per field for alignment, rounded up to the nearest 4 bytes
|
||||
const alignments = if (extra.data.flags.any_aligned_fields)
|
||||
((extra.data.fields_len + 3) / 4) * 4
|
||||
else
|
||||
0;
|
||||
break :b @sizeOf(Tag.TypeUnion) +
|
||||
4 * (@intFromBool(extra.data.flags.any_captures) + captures_len) +
|
||||
(extra.data.fields_len * per_field) + alignments;
|
||||
},
|
||||
|
||||
.type_function => b: {
|
||||
@ -7802,7 +8044,6 @@ pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: NamespaceIndex)
|
||||
.parent = undefined,
|
||||
.file_scope = undefined,
|
||||
.decl_index = undefined,
|
||||
.captures = undefined,
|
||||
};
|
||||
ip.namespaces_free_list.append(gpa, index) catch {
|
||||
// In order to keep `destroyNamespace` a non-fallible function, we ignore memory
|
||||
|
||||
@ -761,37 +761,6 @@ pub const Namespace = struct {
|
||||
/// the Decl Value has to be resolved as a Type which has a Namespace.
|
||||
/// Value is whether the usingnamespace decl is marked `pub`.
|
||||
usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{},
|
||||
/// Allocated into `gpa`.
|
||||
/// The ordered set of values captured in this type's closure.
|
||||
/// `closure_get` instructions look up values in this list.
|
||||
captures: []CaptureValue,
|
||||
|
||||
/// A single value captured in a container's closure. This is not an
|
||||
/// `InternPool.Index` so we can differentiate between runtime-known values
|
||||
/// (where only the type is comptime-known) and comptime-known values.
|
||||
pub const CaptureValue = enum(u32) {
|
||||
_,
|
||||
pub const Unwrapped = union(enum) {
|
||||
/// Index refers to the value.
|
||||
@"comptime": InternPool.Index,
|
||||
/// Index refers to the type.
|
||||
runtime: InternPool.Index,
|
||||
};
|
||||
pub fn wrap(val: Unwrapped) CaptureValue {
|
||||
return switch (val) {
|
||||
.@"comptime" => |i| @enumFromInt(@intFromEnum(i)),
|
||||
.runtime => |i| @enumFromInt((1 << 31) | @intFromEnum(i)),
|
||||
};
|
||||
}
|
||||
pub fn unwrap(val: CaptureValue) Unwrapped {
|
||||
const tag: u1 = @intCast(@intFromEnum(val) >> 31);
|
||||
const raw = @intFromEnum(val);
|
||||
return switch (tag) {
|
||||
0 => .{ .@"comptime" = @enumFromInt(raw) },
|
||||
1 => .{ .runtime = @enumFromInt(@as(u31, @truncate(raw))) },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const Index = InternPool.NamespaceIndex;
|
||||
const OptionalIndex = InternPool.OptionalNamespaceIndex;
|
||||
@ -2130,7 +2099,6 @@ pub fn deinit(zcu: *Zcu) void {
|
||||
while (it.next()) |namespace| {
|
||||
namespace.decls.deinit(gpa);
|
||||
namespace.usingnamespace_set.deinit(gpa);
|
||||
gpa.free(namespace.captures);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3354,7 +3322,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
|
||||
.parent = .none,
|
||||
.decl_index = undefined,
|
||||
.file_scope = file,
|
||||
.captures = &.{},
|
||||
});
|
||||
const new_namespace = mod.namespacePtr(new_namespace_index);
|
||||
errdefer mod.destroyNamespace(new_namespace_index);
|
||||
|
||||
44
src/Sema.zig
44
src/Sema.zig
@ -2670,28 +2670,27 @@ fn analyzeAsInt(
|
||||
}
|
||||
|
||||
/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,
|
||||
/// resolves this into a list of `Namespace.CaptureValue` allocated by `gpa`.
|
||||
/// Caller owns returned memory.
|
||||
fn getCaptures(sema: *Sema, parent_namespace: ?InternPool.NamespaceIndex, extra_index: usize, captures_len: u32) ![]Namespace.CaptureValue {
|
||||
const gpa = sema.gpa;
|
||||
const parent_captures: []const Namespace.CaptureValue = if (parent_namespace) |p| parent: {
|
||||
break :parent sema.mod.namespacePtr(p).captures;
|
||||
} else &.{};
|
||||
/// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`.
|
||||
fn getCaptures(sema: *Sema, parent_namespace: ?InternPool.NamespaceIndex, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {
|
||||
const zcu = sema.mod;
|
||||
const ip = &zcu.intern_pool;
|
||||
const parent_captures: InternPool.CaptureValue.Slice = if (parent_namespace) |p| parent: {
|
||||
break :parent zcu.namespacePtr(p).ty.getCaptures(zcu);
|
||||
} else undefined; // never used so `undefined` is safe
|
||||
|
||||
const captures = try gpa.alloc(Namespace.CaptureValue, captures_len);
|
||||
errdefer gpa.free(captures);
|
||||
const captures = try sema.arena.alloc(InternPool.CaptureValue, captures_len);
|
||||
|
||||
for (sema.code.extra[extra_index..][0..captures_len], captures) |raw, *capture| {
|
||||
const zir_capture: Zir.Inst.Capture = @enumFromInt(raw);
|
||||
capture.* = switch (zir_capture.unwrap()) {
|
||||
.inst => |inst| Namespace.CaptureValue.wrap(capture: {
|
||||
.inst => |inst| InternPool.CaptureValue.wrap(capture: {
|
||||
const air_ref = try sema.resolveInst(inst.toRef());
|
||||
if (try sema.resolveValue(air_ref)) |val| {
|
||||
break :capture .{ .@"comptime" = val.toIntern() };
|
||||
}
|
||||
break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() };
|
||||
}),
|
||||
.nested => |parent_idx| parent_captures[parent_idx],
|
||||
.nested => |parent_idx| parent_captures.get(ip)[parent_idx],
|
||||
};
|
||||
}
|
||||
|
||||
@ -2731,7 +2730,7 @@ pub fn getStructType(
|
||||
break :blk decls_len;
|
||||
} else 0;
|
||||
|
||||
mod.namespacePtr(namespace).captures = try sema.getCaptures(parent_namespace, extra_index, captures_len);
|
||||
const captures = try sema.getCaptures(parent_namespace, extra_index, captures_len);
|
||||
extra_index += captures_len;
|
||||
|
||||
if (small.has_backing_int) {
|
||||
@ -2761,6 +2760,7 @@ pub fn getStructType(
|
||||
.any_comptime_fields = small.any_comptime_fields,
|
||||
.inits_resolved = false,
|
||||
.any_aligned_fields = small.any_aligned_fields,
|
||||
.captures = captures,
|
||||
});
|
||||
|
||||
return ty;
|
||||
@ -2801,7 +2801,6 @@ fn zirStructDecl(
|
||||
.parent = block.namespace.toOptional(),
|
||||
.decl_index = new_decl_index,
|
||||
.file_scope = block.getFileScope(mod),
|
||||
.captures = &.{}, // Will be set by `getStructType`
|
||||
});
|
||||
errdefer mod.destroyNamespace(new_namespace_index);
|
||||
|
||||
@ -2997,7 +2996,6 @@ fn zirEnumDecl(
|
||||
.parent = block.namespace.toOptional(),
|
||||
.decl_index = new_decl_index,
|
||||
.file_scope = block.getFileScope(mod),
|
||||
.captures = captures,
|
||||
});
|
||||
errdefer if (!done) mod.destroyNamespace(new_namespace_index);
|
||||
|
||||
@ -3029,6 +3027,7 @@ fn zirEnumDecl(
|
||||
else
|
||||
.explicit,
|
||||
.zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(),
|
||||
.captures = captures,
|
||||
});
|
||||
if (sema.builtin_type_target_index != .none) {
|
||||
mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, incomplete_enum.index);
|
||||
@ -3261,7 +3260,6 @@ fn zirUnionDecl(
|
||||
.parent = block.namespace.toOptional(),
|
||||
.decl_index = new_decl_index,
|
||||
.file_scope = block.getFileScope(mod),
|
||||
.captures = captures,
|
||||
});
|
||||
errdefer mod.destroyNamespace(new_namespace_index);
|
||||
|
||||
@ -3291,6 +3289,7 @@ fn zirUnionDecl(
|
||||
.enum_tag_ty = .none,
|
||||
.field_types = &.{},
|
||||
.field_aligns = &.{},
|
||||
.captures = captures,
|
||||
});
|
||||
if (sema.builtin_type_target_index != .none) {
|
||||
mod.intern_pool.resolveBuiltinType(sema.builtin_type_target_index, ty);
|
||||
@ -3367,7 +3366,6 @@ fn zirOpaqueDecl(
|
||||
.parent = block.namespace.toOptional(),
|
||||
.decl_index = new_decl_index,
|
||||
.file_scope = block.getFileScope(mod),
|
||||
.captures = captures,
|
||||
});
|
||||
errdefer mod.destroyNamespace(new_namespace_index);
|
||||
|
||||
@ -3375,6 +3373,7 @@ fn zirOpaqueDecl(
|
||||
.decl = new_decl_index,
|
||||
.namespace = new_namespace_index,
|
||||
.zir_index = (try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst)).toOptional(),
|
||||
.captures = captures,
|
||||
});
|
||||
// TODO: figure out InternPool removals for incremental compilation
|
||||
//errdefer mod.intern_pool.remove(opaque_ty);
|
||||
@ -17287,12 +17286,13 @@ fn zirThis(
|
||||
|
||||
fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const captures = mod.namespacePtr(block.namespace).captures;
|
||||
const ip = &mod.intern_pool;
|
||||
const captures = mod.namespacePtr(block.namespace).ty.getCaptures(mod);
|
||||
|
||||
const src_node: i32 = @bitCast(extended.operand);
|
||||
const src = LazySrcLoc.nodeOffset(src_node);
|
||||
|
||||
const capture_ty = switch (captures[extended.small].unwrap()) {
|
||||
const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) {
|
||||
.@"comptime" => |index| return Air.internedToRef(index),
|
||||
.runtime => |index| index,
|
||||
};
|
||||
@ -21360,6 +21360,7 @@ fn zirReify(
|
||||
.explicit,
|
||||
.tag_ty = int_tag_ty.toIntern(),
|
||||
.zir_index = .none,
|
||||
.captures = &.{},
|
||||
});
|
||||
// TODO: figure out InternPool removals for incremental compilation
|
||||
//errdefer ip.remove(incomplete_enum.index);
|
||||
@ -21450,7 +21451,6 @@ fn zirReify(
|
||||
.parent = block.namespace.toOptional(),
|
||||
.decl_index = new_decl_index,
|
||||
.file_scope = block.getFileScope(mod),
|
||||
.captures = &.{},
|
||||
});
|
||||
errdefer mod.destroyNamespace(new_namespace_index);
|
||||
|
||||
@ -21458,6 +21458,7 @@ fn zirReify(
|
||||
.decl = new_decl_index,
|
||||
.namespace = new_namespace_index,
|
||||
.zir_index = .none,
|
||||
.captures = &.{},
|
||||
});
|
||||
// TODO: figure out InternPool removals for incremental compilation
|
||||
//errdefer ip.remove(opaque_ty);
|
||||
@ -21659,7 +21660,6 @@ fn zirReify(
|
||||
.parent = block.namespace.toOptional(),
|
||||
.decl_index = new_decl_index,
|
||||
.file_scope = block.getFileScope(mod),
|
||||
.captures = &.{},
|
||||
});
|
||||
errdefer mod.destroyNamespace(new_namespace_index);
|
||||
|
||||
@ -21688,6 +21688,7 @@ fn zirReify(
|
||||
},
|
||||
.field_types = union_fields.items(.type),
|
||||
.field_aligns = if (any_aligned_fields) union_fields.items(.alignment) else &.{},
|
||||
.captures = &.{},
|
||||
});
|
||||
|
||||
new_decl.ty = Type.type;
|
||||
@ -21849,6 +21850,7 @@ fn reifyStruct(
|
||||
.any_default_inits = true,
|
||||
.inits_resolved = true,
|
||||
.any_aligned_fields = true,
|
||||
.captures = &.{},
|
||||
});
|
||||
// TODO: figure out InternPool removals for incremental compilation
|
||||
//errdefer ip.remove(ty);
|
||||
@ -37404,6 +37406,7 @@ fn generateUnionTagTypeNumbered(
|
||||
.values = enum_field_vals,
|
||||
.tag_mode = .explicit,
|
||||
.zir_index = .none,
|
||||
.captures = &.{},
|
||||
});
|
||||
|
||||
new_decl.ty = Type.type;
|
||||
@ -37455,6 +37458,7 @@ fn generateUnionTagTypeSimple(
|
||||
.values = &.{},
|
||||
.tag_mode = .auto,
|
||||
.zir_index = .none,
|
||||
.captures = &.{},
|
||||
});
|
||||
|
||||
const new_decl = mod.declPtr(new_decl_index);
|
||||
|
||||
12
src/type.zig
12
src/type.zig
@ -3294,6 +3294,18 @@ pub const Type = struct {
|
||||
};
|
||||
}
|
||||
|
||||
/// Given a namespace type, returns its list of caotured values.
|
||||
pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice {
|
||||
const ip = &zcu.intern_pool;
|
||||
return switch (ip.indexToKey(ty.toIntern())) {
|
||||
.struct_type => ip.loadStructType(ty.toIntern()).captures,
|
||||
.union_type => ip.loadUnionType(ty.toIntern()).captures,
|
||||
.enum_type => ip.loadEnumType(ty.toIntern()).captures,
|
||||
.opaque_type => ip.loadOpaqueType(ty.toIntern()).captures,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
pub const @"u1": Type = .{ .ip_index = .u1_type };
|
||||
pub const @"u8": Type = .{ .ip_index = .u8_type };
|
||||
pub const @"u16": Type = .{ .ip_index = .u16_type };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user