mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
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:
parent
7bf91fc79a
commit
9ff514b6a3
21 changed files with 1187 additions and 1574 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
169
src/Module.zig
169
src/Module.zig
|
|
@ -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);
|
||||
|
|
|
|||
821
src/Sema.zig
821
src/Sema.zig
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.*) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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(" = ");
|
||||
|
|
|
|||
|
|
@ -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| {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
|
|
|
|||
1243
src/type.zig
1243
src/type.zig
File diff suppressed because it is too large
Load diff
|
|
@ -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 => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue