compiler: move error union types and error set types to InternPool

One change worth noting in this commit is that `module.global_error_set`
is no longer kept strictly up-to-date. The previous code reserved
integer error values when dealing with error set types, but this is no
longer needed because the integer values are not needed for semantic
analysis unless `@errorToInt` or `@intToError` are used and therefore
may be assigned lazily.
This commit is contained in:
Andrew Kelley 2023-05-20 12:09:07 -07:00
parent 7bf91fc79a
commit 9ff514b6a3
21 changed files with 1187 additions and 1574 deletions

View file

@ -1411,7 +1411,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
.@"try" => {
const err_union_ty = air.typeOf(datas[inst].pl_op.operand, ip);
return err_union_ty.errorUnionPayload();
return ip.indexToKey(err_union_ty.ip_index).error_union_type.payload_type.toType();
},
.work_item_id,

View file

@ -34,6 +34,14 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},
/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.
unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},
/// InferredErrorSet objects are stored in this data structure because:
/// * They contain pointers such as the errors map and the set of other inferred error sets.
/// * They need to be mutated after creation.
allocated_inferred_error_sets: std.SegmentedList(Module.Fn.InferredErrorSet, 0) = .{},
/// When a Struct object is freed from `allocated_inferred_error_sets`, it is
/// pushed into this stack.
inferred_error_sets_free_list: std.ArrayListUnmanaged(Module.Fn.InferredErrorSet.Index) = .{},
/// Some types such as enums, structs, and unions need to store mappings from field names
/// to field index, or value to field index. In such cases, they will store the underlying
/// field names and values directly, relying on one of these maps, stored separately,
@ -113,6 +121,12 @@ pub const NullTerminatedString = enum(u32) {
return std.hash.uint32(@enumToInt(a));
}
};
/// Compare based on integer value alone, ignoring the string contents.
pub fn indexLessThan(ctx: void, a: NullTerminatedString, b: NullTerminatedString) bool {
_ = ctx;
return @enumToInt(a) < @enumToInt(b);
}
};
/// An index into `string_bytes` which might be `none`.
@ -135,10 +149,7 @@ pub const Key = union(enum) {
/// `anyframe->T`. The payload is the child type, which may be `none` to indicate
/// `anyframe`.
anyframe_type: Index,
error_union_type: struct {
error_set_type: Index,
payload_type: Index,
},
error_union_type: ErrorUnionType,
simple_type: SimpleType,
/// This represents a struct that has been explicitly declared in source code,
/// or was created with `@Type`. It is unique and based on a declaration.
@ -152,6 +163,8 @@ pub const Key = union(enum) {
opaque_type: OpaqueType,
enum_type: EnumType,
func_type: FuncType,
error_set_type: ErrorSetType,
inferred_error_set_type: Module.Fn.InferredErrorSet.Index,
/// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
/// via `simple_value` and has a named `Index` tag for it.
@ -183,6 +196,26 @@ pub const Key = union(enum) {
pub const IntType = std.builtin.Type.Int;
pub const ErrorUnionType = struct {
error_set_type: Index,
payload_type: Index,
};
pub const ErrorSetType = struct {
/// Set of error names, sorted by null terminated string index.
names: []const NullTerminatedString,
/// This is ignored by `get` but will always be provided by `indexToKey`.
names_map: OptionalMapIndex = .none,
/// Look up field index based on field name.
pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
const map = &ip.maps.items[@enumToInt(self.names_map.unwrap().?)];
const adapter: NullTerminatedString.Adapter = .{ .strings = self.names };
const field_index = map.getIndexAdapted(name, adapter) orelse return null;
return @intCast(u32, field_index);
}
};
pub const PtrType = struct {
elem_type: Index,
sentinel: Index = .none,
@ -507,6 +540,7 @@ pub const Key = union(enum) {
.un,
.undef,
.enum_tag,
.inferred_error_set_type,
=> |info| std.hash.autoHash(hasher, info),
.opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),
@ -535,7 +569,7 @@ pub const Key = union(enum) {
.ptr => |ptr| {
std.hash.autoHash(hasher, ptr.ty);
// Int-to-ptr pointers are hashed separately than decl-referencing pointers.
// This is sound due to pointer province rules.
// This is sound due to pointer provenance rules.
switch (ptr.addr) {
.int => |int| std.hash.autoHash(hasher, int),
.decl => @panic("TODO"),
@ -547,6 +581,10 @@ pub const Key = union(enum) {
for (aggregate.fields) |field| std.hash.autoHash(hasher, field);
},
.error_set_type => |error_set_type| {
for (error_set_type.names) |elem| std.hash.autoHash(hasher, elem);
},
.anon_struct_type => |anon_struct_type| {
for (anon_struct_type.types) |elem| std.hash.autoHash(hasher, elem);
for (anon_struct_type.values) |elem| std.hash.autoHash(hasher, elem);
@ -726,6 +764,14 @@ pub const Key = union(enum) {
std.mem.eql(Index, a_info.values, b_info.values) and
std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
},
.error_set_type => |a_info| {
const b_info = b.error_set_type;
return std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
},
.inferred_error_set_type => |a_info| {
const b_info = b.inferred_error_set_type;
return a_info == b_info;
},
.func_type => |a_info| {
const b_info = b.func_type;
@ -752,6 +798,8 @@ pub const Key = union(enum) {
.opt_type,
.anyframe_type,
.error_union_type,
.error_set_type,
.inferred_error_set_type,
.simple_type,
.struct_type,
.union_type,
@ -1207,8 +1255,14 @@ pub const Tag = enum(u8) {
/// If the child type is `none`, the type is `anyframe`.
type_anyframe,
/// An error union type.
/// data is payload to ErrorUnion.
/// data is payload to `Key.ErrorUnionType`.
type_error_union,
/// An error set type.
/// data is payload to `ErrorSet`.
type_error_set,
/// The inferred error set type of a function.
/// data is `Module.Fn.InferredErrorSet.Index`.
type_inferred_error_set,
/// An enum type with auto-numbered tag values.
/// The enum is exhaustive.
/// data is payload index to `EnumAuto`.
@ -1355,6 +1409,12 @@ pub const Tag = enum(u8) {
aggregate,
};
/// Trailing:
/// 0. name: NullTerminatedString for each names_len
pub const ErrorSet = struct {
names_len: u32,
};
/// Trailing:
/// 0. param_type: Index for each params_len
pub const TypeFunction = struct {
@ -1539,11 +1599,6 @@ pub const Array = struct {
}
};
pub const ErrorUnion = struct {
error_set_type: Index,
payload_type: Index,
};
/// Trailing:
/// 0. field name: NullTerminatedString for each fields_len; declaration order
/// 1. tag value: Index for each fields_len; declaration order
@ -1719,6 +1774,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
ip.unions_free_list.deinit(gpa);
ip.allocated_unions.deinit(gpa);
ip.inferred_error_sets_free_list.deinit(gpa);
ip.allocated_inferred_error_sets.deinit(gpa);
for (ip.maps.items) |*map| map.deinit(gpa);
ip.maps.deinit(gpa);
@ -1798,7 +1856,18 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
.type_optional => .{ .opt_type = @intToEnum(Index, data) },
.type_anyframe => .{ .anyframe_type = @intToEnum(Index, data) },
.type_error_union => @panic("TODO"),
.type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) },
.type_error_set => {
const error_set = ip.extraDataTrail(ErrorSet, data);
const names_len = error_set.data.names_len;
const names = ip.extra.items[error_set.end..][0..names_len];
return .{ .error_set_type = .{
.names = @ptrCast([]const NullTerminatedString, names),
} };
},
.type_inferred_error_set => .{
.inferred_error_set_type = @intToEnum(Module.Fn.InferredErrorSet.Index, data),
},
.type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
.type_struct => {
@ -2179,11 +2248,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
.error_union_type => |error_union_type| {
ip.items.appendAssumeCapacity(.{
.tag = .type_error_union,
.data = try ip.addExtra(gpa, ErrorUnion{
.error_set_type = error_union_type.error_set_type,
.payload_type = error_union_type.payload_type,
.data = try ip.addExtra(gpa, error_union_type),
});
},
.error_set_type => |error_set_type| {
assert(error_set_type.names_map == .none);
assert(std.sort.isSorted(NullTerminatedString, error_set_type.names, {}, NullTerminatedString.indexLessThan));
const names_map = try ip.addMap(gpa);
try addStringsToMap(ip, gpa, names_map, error_set_type.names);
const names_len = @intCast(u32, error_set_type.names.len);
try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(ErrorSet).Struct.fields.len + names_len);
ip.items.appendAssumeCapacity(.{
.tag = .type_error_set,
.data = ip.addExtraAssumeCapacity(ErrorSet{
.names_len = names_len,
}),
});
ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, error_set_type.names));
},
.inferred_error_set_type => |ies_index| {
ip.items.appendAssumeCapacity(.{
.tag = .type_inferred_error_set,
.data = @enumToInt(ies_index),
});
},
.simple_type => |simple_type| {
ip.items.appendAssumeCapacity(.{
@ -3192,12 +3279,26 @@ pub fn indexToFuncType(ip: InternPool, val: Index) ?Key.FuncType {
}
}
pub fn indexToInferredErrorSetType(ip: InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {
assert(val != .none);
const tags = ip.items.items(.tag);
if (tags[@enumToInt(val)] != .type_inferred_error_set) return .none;
const datas = ip.items.items(.data);
return @intToEnum(Module.Fn.InferredErrorSet.Index, datas[@enumToInt(val)]).toOptional();
}
pub fn isOptionalType(ip: InternPool, ty: Index) bool {
const tags = ip.items.items(.tag);
if (ty == .none) return false;
return tags[@enumToInt(ty)] == .type_optional;
}
pub fn isInferredErrorSetType(ip: InternPool, ty: Index) bool {
const tags = ip.items.items(.tag);
assert(ty != .none);
return tags[@enumToInt(ty)] == .type_inferred_error_set;
}
pub fn dump(ip: InternPool) void {
dumpFallible(ip, std.heap.page_allocator) catch return;
}
@ -3258,7 +3359,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
.type_slice => 0,
.type_optional => 0,
.type_anyframe => 0,
.type_error_union => @sizeOf(ErrorUnion),
.type_error_union => @sizeOf(Key.ErrorUnionType),
.type_error_set => b: {
const info = ip.extraData(ErrorSet, data);
break :b @sizeOf(ErrorSet) + (@sizeOf(u32) * info.names_len);
},
.type_inferred_error_set => @sizeOf(Module.Fn.InferredErrorSet),
.type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
.type_enum_auto => @sizeOf(EnumAuto),
.type_opaque => @sizeOf(Key.OpaqueType),
@ -3359,6 +3465,14 @@ pub fn unionPtr(ip: *InternPool, index: Module.Union.Index) *Module.Union {
return ip.allocated_unions.at(@enumToInt(index));
}
pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {
return ip.allocated_inferred_error_sets.at(@enumToInt(index));
}
pub fn inferredErrorSetPtrConst(ip: InternPool, index: Module.Fn.InferredErrorSet.Index) *const Module.Fn.InferredErrorSet {
return ip.allocated_inferred_error_sets.at(@enumToInt(index));
}
pub fn createStruct(
ip: *InternPool,
gpa: Allocator,
@ -3397,6 +3511,25 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)
};
}
pub fn createInferredErrorSet(
ip: *InternPool,
gpa: Allocator,
initialization: Module.Fn.InferredErrorSet,
) Allocator.Error!Module.Fn.InferredErrorSet.Index {
if (ip.inferred_error_sets_free_list.popOrNull()) |index| return index;
const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);
ptr.* = initialization;
return @intToEnum(Module.Fn.InferredErrorSet.Index, ip.allocated_inferred_error_sets.len - 1);
}
pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.Fn.InferredErrorSet.Index) void {
ip.inferredErrorSetPtr(index).* = undefined;
ip.inferred_error_sets_free_list.append(gpa, index) catch {
// In order to keep `destroyInferredErrorSet` a non-fallible function, we ignore memory
// allocation failures here, instead leaking the InferredErrorSet until garbage collection.
};
}
pub fn getOrPutString(
ip: *InternPool,
gpa: Allocator,
@ -3459,3 +3592,14 @@ pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
else => unreachable,
};
}
pub fn isNoReturn(ip: InternPool, ty: InternPool.Index) bool {
return switch (ty) {
.noreturn_type => true,
else => switch (ip.indexToKey(ty)) {
.error_set_type => |error_set_type| error_set_type.names.len == 0,
.enum_type => |enum_type| enum_type.names.len == 0,
else => false,
},
};
}

View file

@ -1416,7 +1416,7 @@ fn analyzeInstBlock(
// If the block is noreturn, block deaths not only aren't useful, they're impossible to
// find: there could be more stuff alive after the block than before it!
if (!a.air.getRefType(ty_pl.ty).isNoReturn()) {
if (!a.intern_pool.isNoReturn(a.air.getRefType(ty_pl.ty).ip_index)) {
// The block kills the difference in the live sets
const block_scope = data.block_scopes.get(inst).?;
const num_deaths = data.live_set.count() - block_scope.live_set.count();

View file

@ -453,7 +453,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
for (block_liveness.deaths) |death| try self.verifyDeath(inst, death);
if (block_ty.isNoReturn()) {
if (ip.isNoReturn(block_ty.toIntern())) {
assert(!self.blocks.contains(inst));
} else {
var live = self.blocks.fetchRemove(inst).?.value;

View file

@ -960,38 +960,6 @@ pub const EmitH = struct {
fwd_decl: ArrayListUnmanaged(u8) = .{},
};
/// Represents the data that an explicit error set syntax provides.
pub const ErrorSet = struct {
/// The Decl that corresponds to the error set itself.
owner_decl: Decl.Index,
/// The string bytes are stored in the owner Decl arena.
/// These must be in sorted order. See sortNames.
names: NameMap,
pub const NameMap = std.StringArrayHashMapUnmanaged(void);
pub fn srcLoc(self: ErrorSet, mod: *Module) SrcLoc {
const owner_decl = mod.declPtr(self.owner_decl);
return .{
.file_scope = owner_decl.getFileScope(mod),
.parent_decl_node = owner_decl.src_node,
.lazy = LazySrcLoc.nodeOffset(0),
};
}
/// sort the NameMap. This should be called whenever the map is modified.
/// alloc should be the allocator used for the NameMap data.
pub fn sortNames(names: *NameMap) void {
const Context = struct {
keys: [][]const u8,
pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
return std.mem.lessThan(u8, ctx.keys[a_index], ctx.keys[b_index]);
}
};
names.sort(Context{ .keys = names.keys() });
}
};
pub const PropertyBoolean = enum { no, yes, unknown, wip };
/// Represents the data that a struct declaration provides.
@ -1530,13 +1498,6 @@ pub const Fn = struct {
is_noinline: bool,
calls_or_awaits_errorable_fn: bool = false,
/// Any inferred error sets that this function owns, both its own inferred error set and
/// inferred error sets of any inline/comptime functions called. Not to be confused
/// with inferred error sets of generic instantiations of this function, which are
/// *not* tracked here - they are tracked in the new `Fn` object created for the
/// instantiations.
inferred_error_sets: InferredErrorSetList = .{},
pub const Analysis = enum {
/// This function has not yet undergone analysis, because we have not
/// seen a potential runtime call. It may be analyzed in future.
@ -1568,10 +1529,10 @@ pub const Fn = struct {
/// direct additions via `return error.Foo;`, and possibly also errors that
/// are returned from any dependent functions. When the inferred error set is
/// fully resolved, this map contains all the errors that the function might return.
errors: ErrorSet.NameMap = .{},
errors: NameMap = .{},
/// Other inferred error sets which this inferred error set should include.
inferred_error_sets: std.AutoArrayHashMapUnmanaged(*InferredErrorSet, void) = .{},
inferred_error_sets: std.AutoArrayHashMapUnmanaged(InferredErrorSet.Index, void) = .{},
/// Whether the function returned anyerror. This is true if either of
/// the dependent functions returns anyerror.
@ -1581,51 +1542,59 @@ pub const Fn = struct {
/// can skip resolving any dependents of this inferred error set.
is_resolved: bool = false,
pub fn addErrorSet(self: *InferredErrorSet, gpa: Allocator, err_set_ty: Type) !void {
pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
pub const Index = enum(u32) {
_,
pub fn toOptional(i: Index) OptionalIndex {
return @intToEnum(OptionalIndex, @enumToInt(i));
}
};
pub const OptionalIndex = enum(u32) {
none = std.math.maxInt(u32),
_,
pub fn init(oi: ?Index) OptionalIndex {
return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
}
pub fn unwrap(oi: OptionalIndex) ?Index {
if (oi == .none) return null;
return @intToEnum(Index, @enumToInt(oi));
}
};
pub fn addErrorSet(
self: *InferredErrorSet,
err_set_ty: Type,
ip: *InternPool,
gpa: Allocator,
) !void {
switch (err_set_ty.ip_index) {
.anyerror_type => {
self.is_anyerror = true;
},
.none => switch (err_set_ty.tag()) {
.error_set => {
const names = err_set_ty.castTag(.error_set).?.data.names.keys();
for (names) |name| {
else => switch (ip.indexToKey(err_set_ty.ip_index)) {
.error_set_type => |error_set_type| {
for (error_set_type.names) |name| {
try self.errors.put(gpa, name, {});
}
},
.error_set_single => {
const name = err_set_ty.castTag(.error_set_single).?.data;
try self.errors.put(gpa, name, {});
},
.error_set_inferred => {
const ies = err_set_ty.castTag(.error_set_inferred).?.data;
try self.inferred_error_sets.put(gpa, ies, {});
},
.error_set_merged => {
const names = err_set_ty.castTag(.error_set_merged).?.data.keys();
for (names) |name| {
try self.errors.put(gpa, name, {});
}
.inferred_error_set_type => |ies_index| {
try self.inferred_error_sets.put(gpa, ies_index, {});
},
else => unreachable,
},
else => @panic("TODO"),
}
}
};
pub const InferredErrorSetList = std.SinglyLinkedList(InferredErrorSet);
pub const InferredErrorSetListNode = InferredErrorSetList.Node;
/// TODO: remove this function
pub fn deinit(func: *Fn, gpa: Allocator) void {
var it = func.inferred_error_sets.first;
while (it) |node| {
const next = node.next;
node.data.errors.deinit(gpa);
node.data.inferred_error_sets.deinit(gpa);
gpa.destroy(node);
it = next;
}
_ = func;
_ = gpa;
}
pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {
@ -3508,6 +3477,10 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
return mod.intern_pool.structPtr(index);
}
pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet {
return mod.intern_pool.inferredErrorSetPtr(index);
}
/// This one accepts an index from the InternPool and asserts that it is not
/// the anonymous empty struct type.
pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
@ -4722,7 +4695,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
decl_tv.ty.fmt(mod),
});
}
const ty = try decl_tv.val.toType().copy(decl_arena_allocator);
const ty = decl_tv.val.toType();
if (ty.getNamespace(mod) == null) {
return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)});
}
@ -4756,7 +4729,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
}
decl.clearValues(mod);
decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
decl.ty = decl_tv.ty;
decl.val = try decl_tv.val.copy(decl_arena_allocator);
// linksection, align, and addrspace were already set by Sema
decl.has_tv = true;
@ -4823,7 +4796,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
},
}
decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
decl.ty = decl_tv.ty;
decl.val = try decl_tv.val.copy(decl_arena_allocator);
decl.@"align" = blk: {
const align_ref = decl.zirAlignRef(mod);
@ -6599,7 +6572,7 @@ pub fn populateTestFunctions(
// This copy accesses the old Decl Type/Value so it must be done before `clearValues`.
const new_ty = try Type.ptr(arena, mod, .{
.size = .Slice,
.pointee_type = try tmp_test_fn_ty.copy(arena),
.pointee_type = tmp_test_fn_ty,
.mutable = false,
.@"addrspace" = .generic,
});
@ -6877,6 +6850,42 @@ pub fn anyframeType(mod: *Module, payload_ty: Type) Allocator.Error!Type {
return (try intern(mod, .{ .anyframe_type = payload_ty.toIntern() })).toType();
}
pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Allocator.Error!Type {
return (try intern(mod, .{ .error_union_type = .{
.error_set_type = error_set_ty.toIntern(),
.payload_type = payload_ty.toIntern(),
} })).toType();
}
pub fn singleErrorSetType(mod: *Module, name: []const u8) Allocator.Error!Type {
const gpa = mod.gpa;
const ip = &mod.intern_pool;
return singleErrorSetTypeNts(mod, try ip.getOrPutString(gpa, name));
}
pub fn singleErrorSetTypeNts(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type {
const gpa = mod.gpa;
const ip = &mod.intern_pool;
const names = [1]InternPool.NullTerminatedString{name};
const i = try ip.get(gpa, .{ .error_set_type = .{ .names = &names } });
return i.toType();
}
/// Sorts `names` in place.
pub fn errorSetFromUnsortedNames(
mod: *Module,
names: []InternPool.NullTerminatedString,
) Allocator.Error!Type {
std.mem.sort(
InternPool.NullTerminatedString,
names,
{},
InternPool.NullTerminatedString.indexLessThan,
);
const new_ty = try mod.intern(.{ .error_set_type = .{ .names = names } });
return new_ty.toType();
}
/// Supports optionals in addition to pointers.
pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
if (ty.isPtrLikeOptional(mod)) {
@ -7240,6 +7249,16 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {
return mod.intern_pool.indexToFuncType(ty.ip_index);
}
pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*Fn.InferredErrorSet {
const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;
return mod.inferredErrorSetPtr(index);
}
pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) Fn.InferredErrorSet.OptionalIndex {
if (ty.ip_index == .none) return .none;
return mod.intern_pool.indexToInferredErrorSetType(ty.ip_index);
}
pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
@setCold(true);
const owner_decl = mod.declPtr(owner_decl_index);

File diff suppressed because it is too large Load diff

View file

@ -27,13 +27,13 @@ pub const Managed = struct {
/// Assumes arena allocation. Does a recursive copy.
pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue {
return TypedValue{
.ty = try self.ty.copy(arena),
.ty = self.ty,
.val = try self.val.copy(arena),
};
}
pub fn eql(a: TypedValue, b: TypedValue, mod: *Module) bool {
if (!a.ty.eql(b.ty, mod)) return false;
if (a.ty.ip_index != b.ty.ip_index) return false;
return a.val.eql(b.val, a.ty, mod);
}
@ -286,7 +286,7 @@ pub fn print(
.@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
.eu_payload => {
val = val.castTag(.eu_payload).?.data;
ty = ty.errorUnionPayload();
ty = ty.errorUnionPayload(mod);
},
.opt_payload => {
val = val.castTag(.opt_payload).?.data;

View file

@ -3065,8 +3065,8 @@ fn errUnionErr(
maybe_inst: ?Air.Inst.Index,
) !MCValue {
const mod = self.bin_file.options.module.?;
const err_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const err_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
if (err_ty.errorSetIsEmpty(mod)) {
return MCValue{ .immediate = 0 };
}
@ -3145,8 +3145,8 @@ fn errUnionPayload(
maybe_inst: ?Air.Inst.Index,
) !MCValue {
const mod = self.bin_file.options.module.?;
const err_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const err_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
if (err_ty.errorSetIsEmpty(mod)) {
return try error_union_bind.resolveToMcv(self);
}
@ -3305,8 +3305,8 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const error_union_ty = self.air.getRefType(ty_op.ty);
const error_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const error_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
const operand = try self.resolveInst(ty_op.operand);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand;
@ -3329,8 +3329,8 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const mod = self.bin_file.options.module.?;
const error_union_ty = self.air.getRefType(ty_op.ty);
const error_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const error_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
const operand = try self.resolveInst(ty_op.operand);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand;
@ -4893,7 +4893,7 @@ fn isErr(
error_union_ty: Type,
) !MCValue {
const mod = self.bin_file.options.module.?;
const error_type = error_union_ty.errorUnionSet();
const error_type = error_union_ty.errorUnionSet(mod);
if (error_type.errorSetIsEmpty(mod)) {
return MCValue{ .immediate = 0 }; // always false

View file

@ -2042,8 +2042,8 @@ fn errUnionErr(
maybe_inst: ?Air.Inst.Index,
) !MCValue {
const mod = self.bin_file.options.module.?;
const err_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const err_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
if (err_ty.errorSetIsEmpty(mod)) {
return MCValue{ .immediate = 0 };
}
@ -2119,8 +2119,8 @@ fn errUnionPayload(
maybe_inst: ?Air.Inst.Index,
) !MCValue {
const mod = self.bin_file.options.module.?;
const err_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const err_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
if (err_ty.errorSetIsEmpty(mod)) {
return try error_union_bind.resolveToMcv(self);
}
@ -2232,8 +2232,8 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const error_union_ty = self.air.getRefType(ty_op.ty);
const error_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const error_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
const operand = try self.resolveInst(ty_op.operand);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand;
@ -2256,8 +2256,8 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const error_union_ty = self.air.getRefType(ty_op.ty);
const error_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const error_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
const operand = try self.resolveInst(ty_op.operand);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand;
@ -4871,7 +4871,7 @@ fn isErr(
error_union_ty: Type,
) !MCValue {
const mod = self.bin_file.options.module.?;
const error_type = error_union_ty.errorUnionSet();
const error_type = error_union_ty.errorUnionSet(mod);
if (error_type.errorSetIsEmpty(mod)) {
return MCValue{ .immediate = 0 }; // always false

View file

@ -2707,12 +2707,12 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
}
fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
const mod = self.bin_file.options.module.?;
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const error_union_ty = self.typeOf(ty_op.operand);
const payload_ty = error_union_ty.errorUnionPayload();
const payload_ty = error_union_ty.errorUnionPayload(mod);
const mcv = try self.resolveInst(ty_op.operand);
const mod = self.bin_file.options.module.?;
if (!payload_ty.hasRuntimeBits(mod)) break :result mcv;
return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});
@ -2721,11 +2721,11 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
}
fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
const mod = self.bin_file.options.module.?;
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const error_union_ty = self.typeOf(ty_op.operand);
const payload_ty = error_union_ty.errorUnionPayload();
const mod = self.bin_file.options.module.?;
const payload_ty = error_union_ty.errorUnionPayload(mod);
if (!payload_ty.hasRuntimeBits(mod)) break :result MCValue.none;
return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{});
@ -2735,12 +2735,12 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
/// E to E!T
fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
const mod = self.bin_file.options.module.?;
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const error_union_ty = self.air.getRefType(ty_op.ty);
const payload_ty = error_union_ty.errorUnionPayload();
const payload_ty = error_union_ty.errorUnionPayload(mod);
const mcv = try self.resolveInst(ty_op.operand);
const mod = self.bin_file.options.module.?;
if (!payload_ty.hasRuntimeBits(mod)) break :result mcv;
return self.fail("TODO implement wrap errunion error for non-empty payloads", .{});
@ -3529,8 +3529,8 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
/// Given an error union, returns the payload
fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
const mod = self.bin_file.options.module.?;
const err_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const err_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
if (err_ty.errorSetIsEmpty(mod)) {
return error_union_mcv;
}
@ -4168,8 +4168,8 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
const mod = self.bin_file.options.module.?;
const error_type = ty.errorUnionSet();
const payload_type = ty.errorUnionPayload();
const error_type = ty.errorUnionSet(mod);
const payload_type = ty.errorUnionPayload(mod);
if (!error_type.hasRuntimeBits(mod)) {
return MCValue{ .immediate = 0 }; // always false

View file

@ -1264,7 +1264,7 @@ fn genFunc(func: *CodeGen) InnerError!void {
if (func_type.returns.len != 0 and func.air.instructions.len > 0) {
const inst = @intCast(u32, func.air.instructions.len - 1);
const last_inst_ty = func.typeOfIndex(inst);
if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(mod) or last_inst_ty.isNoReturn()) {
if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(mod) or last_inst_ty.isNoReturn(mod)) {
try func.addTag(.@"unreachable");
}
}
@ -1757,7 +1757,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
.Int => return ty.intInfo(mod).bits > 64,
.Float => return ty.floatBits(target) > 64,
.ErrorUnion => {
const pl_ty = ty.errorUnionPayload();
const pl_ty = ty.errorUnionPayload(mod);
if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
return false;
}
@ -2256,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
const result_value = result_value: {
if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) {
break :result_value WValue{ .none = {} };
} else if (ret_ty.isNoReturn()) {
} else if (ret_ty.isNoReturn(mod)) {
try func.addTag(.@"unreachable");
break :result_value WValue{ .none = {} };
} else if (first_param_sret) {
@ -2346,7 +2346,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
const abi_size = ty.abiSize(mod);
switch (ty.zigTypeTag(mod)) {
.ErrorUnion => {
const pl_ty = ty.errorUnionPayload();
const pl_ty = ty.errorUnionPayload(mod);
if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
return func.store(lhs, rhs, Type.anyerror, 0);
}
@ -3111,8 +3111,8 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
else => return WValue{ .imm32 = 0 },
},
.ErrorUnion => {
const error_type = ty.errorUnionSet();
const payload_type = ty.errorUnionPayload();
const error_type = ty.errorUnionSet(mod);
const payload_type = ty.errorUnionPayload(mod);
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
// We use the error type directly as the type.
const is_pl = val.errorUnionIsPayload();
@ -3916,10 +3916,10 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
const un_op = func.air.instructions.items(.data)[inst].un_op;
const operand = try func.resolveInst(un_op);
const err_union_ty = func.typeOf(un_op);
const pl_ty = err_union_ty.errorUnionPayload();
const pl_ty = err_union_ty.errorUnionPayload(mod);
const result = result: {
if (err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
switch (opcode) {
.i32_ne => break :result WValue{ .imm32 = 0 },
.i32_eq => break :result WValue{ .imm32 = 1 },
@ -3953,7 +3953,7 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo
const operand = try func.resolveInst(ty_op.operand);
const op_ty = func.typeOf(ty_op.operand);
const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
const payload_ty = err_ty.errorUnionPayload();
const payload_ty = err_ty.errorUnionPayload(mod);
const result = result: {
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
@ -3981,10 +3981,10 @@ fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool)
const operand = try func.resolveInst(ty_op.operand);
const op_ty = func.typeOf(ty_op.operand);
const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
const payload_ty = err_ty.errorUnionPayload();
const payload_ty = err_ty.errorUnionPayload(mod);
const result = result: {
if (err_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (err_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
break :result WValue{ .imm32 = 0 };
}
@ -4031,7 +4031,7 @@ fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const operand = try func.resolveInst(ty_op.operand);
const err_ty = func.air.getRefType(ty_op.ty);
const pl_ty = err_ty.errorUnionPayload();
const pl_ty = err_ty.errorUnionPayload(mod);
const result = result: {
if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
@ -4044,7 +4044,7 @@ fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
// write 'undefined' to the payload
const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, mod)), .new);
const len = @intCast(u32, err_ty.errorUnionPayload().abiSize(mod));
const len = @intCast(u32, err_ty.errorUnionPayload(mod).abiSize(mod));
try func.memset(Type.u8, payload_ptr, .{ .imm32 = len }, .{ .imm32 = 0xaa });
break :result err_union;
@ -5362,7 +5362,7 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi
const ty_op = func.air.instructions.items(.data)[inst].ty_op;
const err_set_ty = func.typeOf(ty_op.operand).childType(mod);
const payload_ty = err_set_ty.errorUnionPayload();
const payload_ty = err_set_ty.errorUnionPayload(mod);
const operand = try func.resolveInst(ty_op.operand);
// set error-tag to '0' to annotate error union is non-error
@ -6177,10 +6177,10 @@ fn lowerTry(
return func.fail("TODO: lowerTry for pointers", .{});
}
const pl_ty = err_union_ty.errorUnionPayload();
const pl_ty = err_union_ty.errorUnionPayload(mod);
const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(mod);
if (!err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
// Block we can jump out of when error is not set
try func.startBlock(.block, wasm.block_empty);
@ -6742,7 +6742,7 @@ fn callIntrinsic(
if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
return WValue.none;
} else if (return_type.isNoReturn()) {
} else if (return_type.isNoReturn(mod)) {
try func.addTag(.@"unreachable");
return WValue.none;
} else if (want_sret_param) {
@ -6941,20 +6941,21 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
}
fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
const mod = func.bin_file.base.options.module.?;
const ty_op = func.air.instructions.items(.data)[inst].ty_op;
const operand = try func.resolveInst(ty_op.operand);
const error_set_ty = func.air.getRefType(ty_op.ty);
const result = try func.allocLocal(Type.bool);
const names = error_set_ty.errorSetNames();
const names = error_set_ty.errorSetNames(mod);
var values = try std.ArrayList(u32).initCapacity(func.gpa, names.len);
defer values.deinit();
const mod = func.bin_file.base.options.module.?;
var lowest: ?u32 = null;
var highest: ?u32 = null;
for (names) |name| {
for (names) |name_ip| {
const name = mod.intern_pool.stringToSlice(name_ip);
const err_int = mod.global_error_set.get(name).?;
if (lowest) |*l| {
if (err_int < l.*) {

View file

@ -3612,8 +3612,8 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
const mod = self.bin_file.options.module.?;
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const err_union_ty = self.typeOf(ty_op.operand);
const err_ty = err_union_ty.errorUnionSet();
const payload_ty = err_union_ty.errorUnionPayload();
const err_ty = err_union_ty.errorUnionSet(mod);
const payload_ty = err_union_ty.errorUnionPayload(mod);
const operand = try self.resolveInst(ty_op.operand);
const result: MCValue = result: {
@ -3671,7 +3671,7 @@ fn genUnwrapErrorUnionPayloadMir(
err_union: MCValue,
) !MCValue {
const mod = self.bin_file.options.module.?;
const payload_ty = err_union_ty.errorUnionPayload();
const payload_ty = err_union_ty.errorUnionPayload(mod);
const result: MCValue = result: {
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
@ -3731,8 +3731,8 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
defer self.register_manager.unlockReg(dst_lock);
const eu_ty = src_ty.childType(mod);
const pl_ty = eu_ty.errorUnionPayload();
const err_ty = eu_ty.errorUnionSet();
const pl_ty = eu_ty.errorUnionPayload(mod);
const err_ty = eu_ty.errorUnionSet(mod);
const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
const err_abi_size = @intCast(u32, err_ty.abiSize(mod));
try self.asmRegisterMemory(
@ -3771,7 +3771,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
const eu_ty = src_ty.childType(mod);
const pl_ty = eu_ty.errorUnionPayload();
const pl_ty = eu_ty.errorUnionPayload(mod);
const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
try self.asmRegisterMemory(
@ -3797,8 +3797,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
defer self.register_manager.unlockReg(src_lock);
const eu_ty = src_ty.childType(mod);
const pl_ty = eu_ty.errorUnionPayload();
const err_ty = eu_ty.errorUnionSet();
const pl_ty = eu_ty.errorUnionPayload(mod);
const err_ty = eu_ty.errorUnionSet(mod);
const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
const err_abi_size = @intCast(u32, err_ty.abiSize(mod));
try self.asmMemoryImmediate(
@ -3901,8 +3901,8 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const eu_ty = self.air.getRefType(ty_op.ty);
const pl_ty = eu_ty.errorUnionPayload();
const err_ty = eu_ty.errorUnionSet();
const pl_ty = eu_ty.errorUnionPayload(mod);
const err_ty = eu_ty.errorUnionSet(mod);
const operand = try self.resolveInst(ty_op.operand);
const result: MCValue = result: {
@ -3924,8 +3924,8 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const eu_ty = self.air.getRefType(ty_op.ty);
const pl_ty = eu_ty.errorUnionPayload();
const err_ty = eu_ty.errorUnionSet();
const pl_ty = eu_ty.errorUnionPayload(mod);
const err_ty = eu_ty.errorUnionSet(mod);
const result: MCValue = result: {
if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result try self.resolveInst(ty_op.operand);
@ -8782,7 +8782,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
const mod = self.bin_file.options.module.?;
const err_type = ty.errorUnionSet();
const err_type = ty.errorUnionSet(mod);
if (err_type.errorSetIsEmpty(mod)) {
return MCValue{ .immediate = 0 }; // always false
@ -8793,7 +8793,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
self.eflags_inst = inst;
}
const err_off = errUnionErrorOffset(ty.errorUnionPayload(), mod);
const err_off = errUnionErrorOffset(ty.errorUnionPayload(mod), mod);
switch (operand) {
.register => |reg| {
const eu_lock = self.register_manager.lockReg(reg);

View file

@ -139,7 +139,7 @@ pub fn generateLazySymbol(
return generateLazyFunction(bin_file, src_loc, lazy_sym, code, debug_output);
}
if (lazy_sym.ty.isAnyError()) {
if (lazy_sym.ty.isAnyError(mod)) {
alignment.* = 4;
const err_names = mod.error_name_list.items;
mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, err_names.len), endian);
@ -670,8 +670,8 @@ pub fn generateSymbol(
return Result.ok;
},
.ErrorUnion => {
const error_ty = typed_value.ty.errorUnionSet();
const payload_ty = typed_value.ty.errorUnionPayload();
const error_ty = typed_value.ty.errorUnionSet(mod);
const payload_ty = typed_value.ty.errorUnionPayload(mod);
const is_payload = typed_value.val.errorUnionIsPayload();
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
@ -894,7 +894,7 @@ fn lowerParentPtr(
},
.eu_payload_ptr => {
const eu_payload_ptr = parent_ptr.castTag(.eu_payload_ptr).?.data;
const pl_ty = eu_payload_ptr.container_ty.errorUnionPayload();
const pl_ty = eu_payload_ptr.container_ty.errorUnionPayload(mod);
return lowerParentPtr(
bin_file,
src_loc,
@ -1249,8 +1249,8 @@ pub fn genTypedValue(
}
},
.ErrorUnion => {
const error_type = typed_value.ty.errorUnionSet();
const payload_type = typed_value.ty.errorUnionPayload();
const error_type = typed_value.ty.errorUnionSet(mod);
const payload_type = typed_value.ty.errorUnionPayload(mod);
const is_pl = typed_value.val.errorUnionIsPayload();
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {

View file

@ -465,7 +465,7 @@ pub const Function = struct {
}),
},
.data = switch (key) {
.tag_name => .{ .tag_name = try data.tag_name.copy(arena) },
.tag_name => .{ .tag_name = data.tag_name },
.never_tail => .{ .never_tail = data.never_tail },
.never_inline => .{ .never_inline = data.never_inline },
},
@ -862,8 +862,8 @@ pub const DeclGen = struct {
return writer.writeByte('}');
},
.ErrorUnion => {
const payload_ty = ty.errorUnionPayload();
const error_ty = ty.errorUnionSet();
const payload_ty = ty.errorUnionPayload(mod);
const error_ty = ty.errorUnionSet(mod);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
return dg.renderValue(writer, error_ty, val, location);
@ -1252,8 +1252,8 @@ pub const DeclGen = struct {
}
},
.ErrorUnion => {
const payload_ty = ty.errorUnionPayload();
const error_ty = ty.errorUnionSet();
const payload_ty = ty.errorUnionPayload(mod);
const error_ty = ty.errorUnionSet(mod);
const error_val = if (val.errorUnionIsPayload()) try mod.intValue(Type.anyerror, 0) else val;
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
@ -4252,6 +4252,7 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
}
fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
const mod = f.object.dg.module;
const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
const extra = f.air.extraData(Air.Block, ty_pl.payload);
const body = f.air.extra[extra.end..][0..extra.data.body_len];
@ -4284,7 +4285,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
try f.object.indent_writer.insertNewline();
// noreturn blocks have no `br` instructions reaching them, so we don't want a label
if (!f.typeOfIndex(inst).isNoReturn()) {
if (!f.typeOfIndex(inst).isNoReturn(mod)) {
// label must be followed by an expression, include an empty one.
try writer.print("zig_block_{d}:;\n", .{block_id});
}
@ -4322,10 +4323,10 @@ fn lowerTry(
const inst_ty = f.typeOfIndex(inst);
const liveness_condbr = f.liveness.getCondBr(inst);
const writer = f.object.writer();
const payload_ty = err_union_ty.errorUnionPayload();
const payload_ty = err_union_ty.errorUnionPayload(mod);
const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
if (!err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
try writer.writeAll("if (");
if (!payload_has_bits) {
if (is_ptr)
@ -5500,8 +5501,8 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
const operand_is_ptr = operand_ty.zigTypeTag(mod) == .Pointer;
const error_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
const error_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const error_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
const local = try f.allocLocal(inst, inst_ty);
if (!payload_ty.hasRuntimeBits(mod) and operand == .local and operand.local == local.new_local) {
@ -5539,7 +5540,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
const error_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
const writer = f.object.writer();
if (!error_union_ty.errorUnionPayload().hasRuntimeBits(mod)) {
if (!error_union_ty.errorUnionPayload(mod).hasRuntimeBits(mod)) {
if (!is_ptr) return .none;
const local = try f.allocLocal(inst, inst_ty);
@ -5601,9 +5602,9 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const inst_ty = f.typeOfIndex(inst);
const payload_ty = inst_ty.errorUnionPayload();
const payload_ty = inst_ty.errorUnionPayload(mod);
const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
const err_ty = inst_ty.errorUnionSet();
const err_ty = inst_ty.errorUnionSet(mod);
const err = try f.resolveInst(ty_op.operand);
try reap(f, inst, &.{ty_op.operand});
@ -5642,8 +5643,8 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
const operand = try f.resolveInst(ty_op.operand);
const error_union_ty = f.typeOf(ty_op.operand).childType(mod);
const error_ty = error_union_ty.errorUnionSet();
const payload_ty = error_union_ty.errorUnionPayload();
const error_ty = error_union_ty.errorUnionSet(mod);
const payload_ty = error_union_ty.errorUnionPayload(mod);
// First, set the non-error value.
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
@ -5691,10 +5692,10 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const inst_ty = f.typeOfIndex(inst);
const payload_ty = inst_ty.errorUnionPayload();
const payload_ty = inst_ty.errorUnionPayload(mod);
const payload = try f.resolveInst(ty_op.operand);
const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
const err_ty = inst_ty.errorUnionSet();
const err_ty = inst_ty.errorUnionSet(mod);
try reap(f, inst, &.{ty_op.operand});
const writer = f.object.writer();
@ -5729,8 +5730,8 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
const operand_ty = f.typeOf(un_op);
const local = try f.allocLocal(inst, Type.bool);
const err_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
const payload_ty = err_union_ty.errorUnionPayload();
const error_ty = err_union_ty.errorUnionSet();
const payload_ty = err_union_ty.errorUnionPayload(mod);
const error_ty = err_union_ty.errorUnionSet(mod);
try f.writeCValue(writer, local, .Other);
try writer.writeAll(" = ");

View file

@ -1680,14 +1680,14 @@ pub const CType = extern union {
.complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
.payload => unreachable,
}) |fwd_idx| {
const payload_ty = ty.errorUnionPayload();
const payload_ty = ty.errorUnionPayload(mod);
if (try lookup.typeToIndex(payload_ty, switch (kind) {
.forward, .forward_parameter => .forward,
.complete, .parameter => .complete,
.global => .global,
.payload => unreachable,
})) |payload_idx| {
const error_ty = ty.errorUnionSet();
const error_ty = ty.errorUnionSet(mod);
if (payload_idx == Tag.void.toIndex()) {
try self.initType(error_ty, kind, lookup);
} else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| {

View file

@ -362,15 +362,11 @@ pub const Object = struct {
decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *llvm.Value),
/// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction.
named_enum_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *llvm.Value),
/// Maps Zig types to LLVM types. The table memory itself is backed by the GPA of
/// the compiler, but the Type/Value memory here is backed by `type_map_arena`.
/// TODO we need to remove entries from this map in response to incremental compilation
/// but I think the frontend won't tell us about types that get deleted because
/// hasRuntimeBits() is false for types.
/// Maps Zig types to LLVM types. The table memory is backed by the GPA of
/// the compiler.
/// TODO when InternPool garbage collection is implemented, this map needs
/// to be garbage collected as well.
type_map: TypeMap,
/// The backing memory for `type_map`. Periodically garbage collected after flush().
/// The code for doing the periodical GC is not yet implemented.
type_map_arena: std.heap.ArenaAllocator,
di_type_map: DITypeMap,
/// The LLVM global table which holds the names corresponding to Zig errors.
/// Note that the values are not added until flushModule, when all errors in
@ -381,12 +377,7 @@ pub const Object = struct {
/// name collision.
extern_collisions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void),
pub const TypeMap = std.HashMapUnmanaged(
Type,
*llvm.Type,
Type.HashContext64,
std.hash_map.default_max_load_percentage,
);
pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, *llvm.Type);
/// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we
/// want to iterate over it while adding entries to it.
@ -543,7 +534,6 @@ pub const Object = struct {
.decl_map = .{},
.named_enum_map = .{},
.type_map = .{},
.type_map_arena = std.heap.ArenaAllocator.init(gpa),
.di_type_map = .{},
.error_name_table = null,
.extern_collisions = .{},
@ -563,7 +553,6 @@ pub const Object = struct {
self.decl_map.deinit(gpa);
self.named_enum_map.deinit(gpa);
self.type_map.deinit(gpa);
self.type_map_arena.deinit();
self.extern_collisions.deinit(gpa);
self.* = undefined;
}
@ -1462,9 +1451,6 @@ pub const Object = struct {
return o.lowerDebugTypeImpl(entry, resolve, di_type);
}
errdefer assert(o.di_type_map.orderedRemoveContext(ty, .{ .mod = o.module }));
// The Type memory is ephemeral; since we want to store a longer-lived
// reference, we need to copy it here.
gop.key_ptr.* = try ty.copy(o.type_map_arena.allocator());
const entry: Object.DITypeMap.Entry = .{
.key_ptr = gop.key_ptr,
.value_ptr = gop.value_ptr,
@ -1868,7 +1854,7 @@ pub const Object = struct {
return full_di_ty;
},
.ErrorUnion => {
const payload_ty = ty.errorUnionPayload();
const payload_ty = ty.errorUnionPayload(mod);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
@ -2823,7 +2809,7 @@ pub const DeclGen = struct {
.Opaque => {
if (t.ip_index == .anyopaque_type) return dg.context.intType(8);
const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = mod });
const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern());
if (gop.found_existing) return gop.value_ptr.*;
const opaque_type = mod.intern_pool.indexToKey(t.ip_index).opaque_type;
@ -2869,7 +2855,7 @@ pub const DeclGen = struct {
return dg.context.structType(&fields_buf, 3, .False);
},
.ErrorUnion => {
const payload_ty = t.errorUnionPayload();
const payload_ty = t.errorUnionPayload(mod);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
return try dg.lowerType(Type.anyerror);
}
@ -2913,13 +2899,9 @@ pub const DeclGen = struct {
},
.ErrorSet => return dg.context.intType(16),
.Struct => {
const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = mod });
const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern());
if (gop.found_existing) return gop.value_ptr.*;
// The Type memory is ephemeral; since we want to store a longer-lived
// reference, we need to copy it here.
gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
const struct_type = switch (mod.intern_pool.indexToKey(t.ip_index)) {
.anon_struct_type => |tuple| {
const llvm_struct_ty = dg.context.structCreateNamed("");
@ -3041,13 +3023,9 @@ pub const DeclGen = struct {
return llvm_struct_ty;
},
.Union => {
const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = mod });
const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern());
if (gop.found_existing) return gop.value_ptr.*;
// The Type memory is ephemeral; since we want to store a longer-lived
// reference, we need to copy it here.
gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
const layout = t.unionGetLayout(mod);
const union_obj = mod.typeToUnion(t).?;
@ -3571,7 +3549,7 @@ pub const DeclGen = struct {
}
},
.ErrorUnion => {
const payload_type = tv.ty.errorUnionPayload();
const payload_type = tv.ty.errorUnionPayload(mod);
const is_pl = tv.val.errorUnionIsPayload();
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
@ -4130,7 +4108,7 @@ pub const DeclGen = struct {
const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, true);
const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload();
const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload(mod);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
// In this case, we represent pointer to error union the same as pointer
// to the payload.
@ -5368,7 +5346,7 @@ pub const FuncGen = struct {
const inst_ty = self.typeOfIndex(inst);
const parent_bb = self.context.createBasicBlock("Block");
if (inst_ty.isNoReturn()) {
if (inst_ty.isNoReturn(mod)) {
try self.genBody(body);
return null;
}
@ -5490,11 +5468,11 @@ pub const FuncGen = struct {
is_unused: bool,
) !?*llvm.Value {
const mod = fg.dg.module;
const payload_ty = err_union_ty.errorUnionPayload();
const payload_ty = err_union_ty.errorUnionPayload(mod);
const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty);
if (!err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
const is_err = err: {
const err_set_ty = try fg.dg.lowerType(Type.anyerror);
const zero = err_set_ty.constNull();
@ -5601,6 +5579,7 @@ pub const FuncGen = struct {
}
fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
const mod = self.dg.module;
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const loop = self.air.extraData(Air.Block, ty_pl.payload);
const body = self.air.extra[loop.end..][0..loop.data.body_len];
@ -5616,7 +5595,7 @@ pub const FuncGen = struct {
// would have been emitted already. Also the main loop in genBody can
// be while(true) instead of for(body), which will eliminate 1 branch on
// a hot path.
if (body.len == 0 or !self.typeOfIndex(body[body.len - 1]).isNoReturn()) {
if (body.len == 0 or !self.typeOfIndex(body[body.len - 1]).isNoReturn(mod)) {
_ = self.builder.buildBr(loop_block);
}
return null;
@ -6674,11 +6653,11 @@ pub const FuncGen = struct {
const operand = try self.resolveInst(un_op);
const operand_ty = self.typeOf(un_op);
const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
const payload_ty = err_union_ty.errorUnionPayload();
const payload_ty = err_union_ty.errorUnionPayload(mod);
const err_set_ty = try self.dg.lowerType(Type.anyerror);
const zero = err_set_ty.constNull();
if (err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
const llvm_i1 = self.context.intType(1);
switch (op) {
.EQ => return llvm_i1.constInt(1, .False), // 0 == 0
@ -6825,7 +6804,7 @@ pub const FuncGen = struct {
const operand = try self.resolveInst(ty_op.operand);
const operand_ty = self.typeOf(ty_op.operand);
const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
if (err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
const err_llvm_ty = try self.dg.lowerType(Type.anyerror);
if (operand_is_ptr) {
return operand;
@ -6836,7 +6815,7 @@ pub const FuncGen = struct {
const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror);
const payload_ty = err_union_ty.errorUnionPayload();
const payload_ty = err_union_ty.errorUnionPayload(mod);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
if (!operand_is_ptr) return operand;
return self.builder.buildLoad(err_set_llvm_ty, operand, "");
@ -6859,7 +6838,7 @@ pub const FuncGen = struct {
const operand = try self.resolveInst(ty_op.operand);
const err_union_ty = self.typeOf(ty_op.operand).childType(mod);
const payload_ty = err_union_ty.errorUnionPayload();
const payload_ty = err_union_ty.errorUnionPayload(mod);
const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = try mod.intValue(Type.err_int, 0) });
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
_ = self.builder.buildStore(non_error_val, operand);
@ -6968,7 +6947,7 @@ pub const FuncGen = struct {
const mod = self.dg.module;
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const err_un_ty = self.typeOfIndex(inst);
const payload_ty = err_un_ty.errorUnionPayload();
const payload_ty = err_un_ty.errorUnionPayload(mod);
const operand = try self.resolveInst(ty_op.operand);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
return operand;
@ -8787,13 +8766,14 @@ pub const FuncGen = struct {
const operand = try self.resolveInst(ty_op.operand);
const error_set_ty = self.air.getRefType(ty_op.ty);
const names = error_set_ty.errorSetNames();
const names = error_set_ty.errorSetNames(mod);
const valid_block = self.context.appendBasicBlock(self.llvm_func, "Valid");
const invalid_block = self.context.appendBasicBlock(self.llvm_func, "Invalid");
const end_block = self.context.appendBasicBlock(self.llvm_func, "End");
const switch_instr = self.builder.buildSwitch(operand, invalid_block, @intCast(c_uint, names.len));
for (names) |name| {
for (names) |name_ip| {
const name = mod.intern_pool.stringToSlice(name_ip);
const err_int = mod.global_error_set.get(name).?;
const this_tag_int_value = try self.dg.lowerValue(.{
.ty = Type.err_int,
@ -11095,7 +11075,7 @@ fn isByRef(ty: Type, mod: *Module) bool {
else => return ty.hasRuntimeBits(mod),
},
.ErrorUnion => {
const payload_ty = ty.errorUnionPayload();
const payload_ty = ty.errorUnionPayload(mod);
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
return false;
}

View file

@ -801,7 +801,7 @@ pub const DeclGen = struct {
},
},
.ErrorUnion => {
const payload_ty = ty.errorUnionPayload();
const payload_ty = ty.errorUnionPayload(mod);
const is_pl = val.errorUnionIsPayload();
const error_val = if (!is_pl) val else try mod.intValue(Type.anyerror, 0);
@ -1365,7 +1365,7 @@ pub const DeclGen = struct {
.Union => return try self.resolveUnionType(ty, null),
.ErrorSet => return try self.intType(.unsigned, 16),
.ErrorUnion => {
const payload_ty = ty.errorUnionPayload();
const payload_ty = ty.errorUnionPayload(mod);
const error_ty_ref = try self.resolveType(Type.anyerror, .indirect);
const eu_layout = self.errorUnionLayout(payload_ty);
@ -2875,7 +2875,7 @@ pub const DeclGen = struct {
const eu_layout = self.errorUnionLayout(payload_ty);
if (!err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
const err_id = if (eu_layout.payload_has_bits)
try self.extractField(Type.anyerror, err_union_id, eu_layout.errorFieldIndex())
else
@ -2929,12 +2929,12 @@ pub const DeclGen = struct {
const err_union_ty = self.typeOf(ty_op.operand);
const err_ty_ref = try self.resolveType(Type.anyerror, .direct);
if (err_union_ty.errorUnionSet().errorSetIsEmpty(mod)) {
if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
// No error possible, so just return undefined.
return try self.spv.constUndef(err_ty_ref);
}
const payload_ty = err_union_ty.errorUnionPayload();
const payload_ty = err_union_ty.errorUnionPayload(mod);
const eu_layout = self.errorUnionLayout(payload_ty);
if (!eu_layout.payload_has_bits) {
@ -2948,9 +2948,10 @@ pub const DeclGen = struct {
fn airWrapErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
if (self.liveness.isUnused(inst)) return null;
const mod = self.module;
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const err_union_ty = self.typeOfIndex(inst);
const payload_ty = err_union_ty.errorUnionPayload();
const payload_ty = err_union_ty.errorUnionPayload(mod);
const operand_id = try self.resolve(ty_op.operand);
const eu_layout = self.errorUnionLayout(payload_ty);

View file

@ -18,6 +18,7 @@ const LinkBlock = File.LinkBlock;
const LinkFn = File.LinkFn;
const LinkerLoad = @import("../codegen.zig").LinkerLoad;
const Module = @import("../Module.zig");
const InternPool = @import("../InternPool.zig");
const StringTable = @import("strtab.zig").StringTable;
const Type = @import("../type.zig").Type;
const Value = @import("../value.zig").Value;
@ -518,9 +519,9 @@ pub const DeclState = struct {
);
},
.ErrorUnion => {
const error_ty = ty.errorUnionSet();
const payload_ty = ty.errorUnionPayload();
const payload_align = if (payload_ty.isNoReturn()) 0 else payload_ty.abiAlignment(mod);
const error_ty = ty.errorUnionSet(mod);
const payload_ty = ty.errorUnionPayload(mod);
const payload_align = if (payload_ty.isNoReturn(mod)) 0 else payload_ty.abiAlignment(mod);
const error_align = Type.anyerror.abiAlignment(mod);
const abi_size = ty.abiSize(mod);
const payload_off = if (error_align >= payload_align) Type.anyerror.abiSize(mod) else 0;
@ -534,7 +535,7 @@ pub const DeclState = struct {
const name = try ty.nameAllocArena(arena, mod);
try dbg_info_buffer.writer().print("{s}\x00", .{name});
if (!payload_ty.isNoReturn()) {
if (!payload_ty.isNoReturn(mod)) {
// DW.AT.member
try dbg_info_buffer.ensureUnusedCapacity(7);
dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
@ -1266,10 +1267,11 @@ pub fn commitDeclState(
const symbol = &decl_state.abbrev_table.items[sym_index];
const ty = symbol.type;
const deferred: bool = blk: {
if (ty.isAnyError()) break :blk true;
switch (ty.tag()) {
.error_set_inferred => {
if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;
if (ty.isAnyError(mod)) break :blk true;
switch (mod.intern_pool.indexToKey(ty.ip_index)) {
.inferred_error_set_type => |ies_index| {
const ies = mod.inferredErrorSetPtr(ies_index);
if (!ies.is_resolved) break :blk true;
},
else => {},
}
@ -1290,10 +1292,11 @@ pub fn commitDeclState(
const symbol = decl_state.abbrev_table.items[target];
const ty = symbol.type;
const deferred: bool = blk: {
if (ty.isAnyError()) break :blk true;
switch (ty.tag()) {
.error_set_inferred => {
if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;
if (ty.isAnyError(mod)) break :blk true;
switch (mod.intern_pool.indexToKey(ty.ip_index)) {
.inferred_error_set_type => |ies_index| {
const ies = mod.inferredErrorSetPtr(ies_index);
if (!ies.is_resolved) break :blk true;
},
else => {},
}
@ -2529,18 +2532,22 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
defer arena_alloc.deinit();
const arena = arena_alloc.allocator();
const error_set = try arena.create(Module.ErrorSet);
const error_ty = try Type.Tag.error_set.create(arena, error_set);
var names = Module.ErrorSet.NameMap{};
try names.ensureUnusedCapacity(arena, module.global_error_set.count());
var it = module.global_error_set.keyIterator();
while (it.next()) |key| {
names.putAssumeCapacityNoClobber(key.*, {});
// TODO: don't create a zig type for this, just make the dwarf info
// without touching the zig type system.
const names = try arena.alloc(InternPool.NullTerminatedString, module.global_error_set.count());
{
var it = module.global_error_set.keyIterator();
var i: usize = 0;
while (it.next()) |key| : (i += 1) {
names[i] = module.intern_pool.getString(key.*).unwrap().?;
}
}
error_set.names = names;
std.mem.sort(InternPool.NullTerminatedString, names, {}, InternPool.NullTerminatedString.indexLessThan);
const error_ty = try module.intern(.{ .error_set_type = .{ .names = names } });
var dbg_info_buffer = std.ArrayList(u8).init(arena);
try addDbgInfoErrorSet(arena, module, error_ty, self.target, &dbg_info_buffer);
try addDbgInfoErrorSet(arena, module, error_ty.toType(), self.target, &dbg_info_buffer);
const di_atom_index = try self.createAtom(.di_atom);
log.debug("updateDeclDebugInfoAllocation in flushModule", .{});
@ -2684,8 +2691,9 @@ fn addDbgInfoErrorSet(
// DW.AT.const_value, DW.FORM.data8
mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
const error_names = ty.errorSetNames();
for (error_names) |error_name| {
const error_names = ty.errorSetNames(mod);
for (error_names) |error_name_ip| {
const error_name = mod.intern_pool.stringToSlice(error_name_ip);
const kv = mod.getErrorValue(error_name) catch unreachable;
// DW.AT.enumerator
try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));

View file

@ -370,7 +370,6 @@ const Writer = struct {
.none => switch (ty.tag()) {
.inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),
.inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),
else => try ty.print(s, w.module),
},
else => try ty.print(s, w.module),
}

File diff suppressed because it is too large Load diff

View file

@ -260,7 +260,7 @@ pub const Value = struct {
const new_payload = try arena.create(Payload.Ty);
new_payload.* = .{
.base = payload.base,
.data = try payload.data.copy(arena),
.data = payload.data,
};
return Value{
.ip_index = .none,
@ -281,7 +281,7 @@ pub const Value = struct {
.base = payload.base,
.data = .{
.container_ptr = try payload.data.container_ptr.copy(arena),
.container_ty = try payload.data.container_ty.copy(arena),
.container_ty = payload.data.container_ty,
},
};
return Value{
@ -296,7 +296,7 @@ pub const Value = struct {
.base = payload.base,
.data = .{
.field_val = try payload.data.field_val.copy(arena),
.field_ty = try payload.data.field_ty.copy(arena),
.field_ty = payload.data.field_ty,
},
};
return Value{
@ -311,7 +311,7 @@ pub const Value = struct {
.base = payload.base,
.data = .{
.array_ptr = try payload.data.array_ptr.copy(arena),
.elem_ty = try payload.data.elem_ty.copy(arena),
.elem_ty = payload.data.elem_ty,
.index = payload.data.index,
},
};
@ -327,7 +327,7 @@ pub const Value = struct {
.base = payload.base,
.data = .{
.container_ptr = try payload.data.container_ptr.copy(arena),
.container_ty = try payload.data.container_ty.copy(arena),
.container_ty = payload.data.container_ty,
.field_index = payload.data.field_index,
},
};
@ -1870,7 +1870,7 @@ pub const Value = struct {
.eu_payload => {
const a_payload = a.castTag(.eu_payload).?.data;
const b_payload = b.castTag(.eu_payload).?.data;
const payload_ty = ty.errorUnionPayload();
const payload_ty = ty.errorUnionPayload(mod);
return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, opt_sema);
},
.eu_payload_ptr => {
@ -2163,14 +2163,14 @@ pub const Value = struct {
.ErrorUnion => {
if (val.tag() == .@"error") {
std.hash.autoHash(hasher, false); // error
const sub_ty = ty.errorUnionSet();
const sub_ty = ty.errorUnionSet(mod);
val.hash(sub_ty, hasher, mod);
return;
}
if (val.castTag(.eu_payload)) |payload| {
std.hash.autoHash(hasher, true); // payload
const sub_ty = ty.errorUnionPayload();
const sub_ty = ty.errorUnionPayload(mod);
payload.data.hash(sub_ty, hasher, mod);
return;
} else unreachable;
@ -2272,7 +2272,7 @@ pub const Value = struct {
payload.data.hashUncoerced(child_ty, hasher, mod);
} else std.hash.autoHash(hasher, std.builtin.TypeId.Null),
.ErrorSet, .ErrorUnion => if (val.getError()) |err| hasher.update(err) else {
const pl_ty = ty.errorUnionPayload();
const pl_ty = ty.errorUnionPayload(mod);
val.castTag(.eu_payload).?.data.hashUncoerced(pl_ty, hasher, mod);
},
.Enum, .EnumLiteral, .Union => {