authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-10 21:39:11-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-10 21:39:55-04:00
logc2316c52285b1319d7b44a7f7135d9e79786fd77
tree966c3af5bb0ede2e3f1e7ec69a3bf920c0122914
parent98f3a262a7aec25e0a7f0872dc7fafc9008be1d2

InternPool: make `global_error_set` thread-safe


15 files changed, 252 insertions(+), 96 deletions(-)

src/Compilation.zig+2-2
...@@ -2943,7 +2943,7 @@ pub fn totalErrorCount(comp: *Compilation) u32 {...@@ -2943,7 +2943,7 @@ pub fn totalErrorCount(comp: *Compilation) u32 {
2943 }2943 }
2944 }2944 }
29452945
2946 if (zcu.global_error_set.entries.len - 1 > zcu.error_limit) {2946 if (zcu.intern_pool.global_error_set.mutate.list.len > zcu.error_limit) {
2947 total += 1;2947 total += 1;
2948 }2948 }
2949 }2949 }
...@@ -3072,7 +3072,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3072,7 +3072,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3072 try addModuleErrorMsg(zcu, &bundle, value.*, &all_references);3072 try addModuleErrorMsg(zcu, &bundle, value.*, &all_references);
3073 }3073 }
30743074
3075 const actual_error_count = zcu.global_error_set.entries.len - 1;3075 const actual_error_count = zcu.intern_pool.global_error_set.mutate.list.len;
3076 if (actual_error_count > zcu.error_limit) {3076 if (actual_error_count > zcu.error_limit) {
3077 try bundle.addRootErrorMessage(.{3077 try bundle.addRootErrorMessage(.{
3078 .msg = try bundle.printString("ZCU used more errors than possible: used {d}, max {d}", .{3078 .msg = try bundle.printString("ZCU used more errors than possible: used {d}, max {d}", .{
src/InternPool.zig+160-2
...@@ -6,6 +6,8 @@ locals: []Local = &.{},...@@ -6,6 +6,8 @@ locals: []Local = &.{},
6/// Length must be a power of two and represents the number of simultaneous6/// Length must be a power of two and represents the number of simultaneous
7/// writers that can mutate any single sharded data structure.7/// writers that can mutate any single sharded data structure.
8shards: []Shard = &.{},8shards: []Shard = &.{},
9/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
10global_error_set: GlobalErrorSet = GlobalErrorSet.empty,
9/// Cached number of active bits in a `tid`.11/// Cached number of active bits in a `tid`.
10tid_width: if (single_threaded) u0 else std.math.Log2Int(u32) = 0,12tid_width: if (single_threaded) u0 else std.math.Log2Int(u32) = 0,
11/// Cached shift amount to put a `tid` in the top bits of a 31-bit value.13/// Cached shift amount to put a `tid` in the top bits of a 31-bit value.
...@@ -10129,10 +10131,10 @@ pub fn getOrPutTrailingString(...@@ -10129,10 +10131,10 @@ pub fn getOrPutTrailingString(
10129 defer shard.mutate.string_map.len += 1;10131 defer shard.mutate.string_map.len += 1;
10130 const map_header = map.header().*;10132 const map_header = map.header().*;
10131 if (shard.mutate.string_map.len < map_header.capacity * 3 / 5) {10133 if (shard.mutate.string_map.len < map_header.capacity * 3 / 5) {
10134 strings.appendAssumeCapacity(.{0});
10132 const entry = &map.entries[map_index];10135 const entry = &map.entries[map_index];
10133 entry.hash = hash;10136 entry.hash = hash;
10134 entry.release(@enumFromInt(@intFromEnum(value)));10137 entry.release(@enumFromInt(@intFromEnum(value)));
10135 strings.appendAssumeCapacity(.{0});
10136 return value;10138 return value;
10137 }10139 }
10138 const arena_state = &ip.getLocal(tid).mutate.arena;10140 const arena_state = &ip.getLocal(tid).mutate.arena;
...@@ -10171,12 +10173,12 @@ pub fn getOrPutTrailingString(...@@ -10171,12 +10173,12 @@ pub fn getOrPutTrailingString(
10171 map_index &= new_map_mask;10173 map_index &= new_map_mask;
10172 if (map.entries[map_index].value == .none) break;10174 if (map.entries[map_index].value == .none) break;
10173 }10175 }
10176 strings.appendAssumeCapacity(.{0});
10174 map.entries[map_index] = .{10177 map.entries[map_index] = .{
10175 .value = @enumFromInt(@intFromEnum(value)),10178 .value = @enumFromInt(@intFromEnum(value)),
10176 .hash = hash,10179 .hash = hash,
10177 };10180 };
10178 shard.shared.string_map.release(new_map);10181 shard.shared.string_map.release(new_map);
10179 strings.appendAssumeCapacity(.{0});
10180 return value;10182 return value;
10181}10183}
1018210184
...@@ -10942,3 +10944,159 @@ fn ptrsHaveSameAlignment(ip: *InternPool, a_ty: Index, a_info: Key.PtrType, b_ty...@@ -10942,3 +10944,159 @@ fn ptrsHaveSameAlignment(ip: *InternPool, a_ty: Index, a_info: Key.PtrType, b_ty
10942 return a_info.flags.alignment == b_info.flags.alignment and10944 return a_info.flags.alignment == b_info.flags.alignment and
10943 (a_info.child == b_info.child or a_info.flags.alignment != .none);10945 (a_info.child == b_info.child or a_info.flags.alignment != .none);
10944}10946}
10947
10948const GlobalErrorSet = struct {
10949 shared: struct {
10950 names: Names,
10951 map: Shard.Map(GlobalErrorSet.Index),
10952 } align(std.atomic.cache_line),
10953 mutate: Local.MutexListMutate align(std.atomic.cache_line),
10954
10955 const Names = Local.List(struct { NullTerminatedString });
10956
10957 const empty: GlobalErrorSet = .{
10958 .shared = .{
10959 .names = Names.empty,
10960 .map = Shard.Map(GlobalErrorSet.Index).empty,
10961 },
10962 .mutate = Local.MutexListMutate.empty,
10963 };
10964
10965 const Index = enum(Zcu.ErrorInt) {
10966 none = 0,
10967 _,
10968 };
10969
10970 /// Not thread-safe, may only be called from the main thread.
10971 pub fn getNamesFromMainThread(ges: *const GlobalErrorSet) []const NullTerminatedString {
10972 return ges.shared.names.view().items(.@"0")[0..ges.mutate.list.len];
10973 }
10974
10975 fn getErrorValue(
10976 ges: *GlobalErrorSet,
10977 gpa: Allocator,
10978 arena_state: *std.heap.ArenaAllocator.State,
10979 name: NullTerminatedString,
10980 ) Allocator.Error!GlobalErrorSet.Index {
10981 if (name == .empty) return .none;
10982 const hash = std.hash.uint32(@intFromEnum(name));
10983 var map = ges.shared.map.acquire();
10984 const Map = @TypeOf(map);
10985 var map_mask = map.header().mask();
10986 const names = ges.shared.names.acquire();
10987 var map_index = hash;
10988 while (true) : (map_index += 1) {
10989 map_index &= map_mask;
10990 const entry = &map.entries[map_index];
10991 const index = entry.acquire();
10992 if (index == .none) break;
10993 if (entry.hash != hash) continue;
10994 if (names.view().items(.@"0")[@intFromEnum(index) - 1] == name) return index;
10995 }
10996 ges.mutate.mutex.lock();
10997 defer ges.mutate.mutex.unlock();
10998 if (map.entries != ges.shared.map.entries) {
10999 map = ges.shared.map;
11000 map_mask = map.header().mask();
11001 map_index = hash;
11002 }
11003 while (true) : (map_index += 1) {
11004 map_index &= map_mask;
11005 const entry = &map.entries[map_index];
11006 const index = entry.value;
11007 if (index == .none) break;
11008 if (entry.hash != hash) continue;
11009 if (names.view().items(.@"0")[@intFromEnum(index) - 1] == name) return index;
11010 }
11011 const mutable_names: Names.Mutable = .{
11012 .gpa = gpa,
11013 .arena = arena_state,
11014 .mutate = &ges.mutate.list,
11015 .list = &ges.shared.names,
11016 };
11017 try mutable_names.ensureUnusedCapacity(1);
11018 const map_header = map.header().*;
11019 if (ges.mutate.list.len < map_header.capacity * 3 / 5) {
11020 mutable_names.appendAssumeCapacity(.{name});
11021 const index: GlobalErrorSet.Index = @enumFromInt(mutable_names.mutate.len);
11022 const entry = &map.entries[map_index];
11023 entry.hash = hash;
11024 entry.release(index);
11025 return index;
11026 }
11027 var arena = arena_state.promote(gpa);
11028 defer arena_state.* = arena.state;
11029 const new_map_capacity = map_header.capacity * 2;
11030 const new_map_buf = try arena.allocator().alignedAlloc(
11031 u8,
11032 Map.alignment,
11033 Map.entries_offset + new_map_capacity * @sizeOf(Map.Entry),
11034 );
11035 const new_map: Map = .{ .entries = @ptrCast(new_map_buf[Map.entries_offset..].ptr) };
11036 new_map.header().* = .{ .capacity = new_map_capacity };
11037 @memset(new_map.entries[0..new_map_capacity], .{ .value = .none, .hash = undefined });
11038 const new_map_mask = new_map.header().mask();
11039 map_index = 0;
11040 while (map_index < map_header.capacity) : (map_index += 1) {
11041 const entry = &map.entries[map_index];
11042 const index = entry.value;
11043 if (index == .none) continue;
11044 const item_hash = entry.hash;
11045 var new_map_index = item_hash;
11046 while (true) : (new_map_index += 1) {
11047 new_map_index &= new_map_mask;
11048 const new_entry = &new_map.entries[new_map_index];
11049 if (new_entry.value != .none) continue;
11050 new_entry.* = .{
11051 .value = index,
11052 .hash = item_hash,
11053 };
11054 break;
11055 }
11056 }
11057 map = new_map;
11058 map_index = hash;
11059 while (true) : (map_index += 1) {
11060 map_index &= new_map_mask;
11061 if (map.entries[map_index].value == .none) break;
11062 }
11063 mutable_names.appendAssumeCapacity(.{name});
11064 const index: GlobalErrorSet.Index = @enumFromInt(mutable_names.mutate.len);
11065 map.entries[map_index] = .{ .value = index, .hash = hash };
11066 ges.shared.map.release(new_map);
11067 return index;
11068 }
11069
11070 fn getErrorValueIfExists(
11071 ges: *const GlobalErrorSet,
11072 name: NullTerminatedString,
11073 ) ?GlobalErrorSet.Index {
11074 if (name == .empty) return .none;
11075 const hash = std.hash.uint32(@intFromEnum(name));
11076 const map = ges.shared.map.acquire();
11077 const map_mask = map.header().mask();
11078 const names_items = ges.shared.names.acquire().view().items(.@"0");
11079 var map_index = hash;
11080 while (true) : (map_index += 1) {
11081 map_index &= map_mask;
11082 const entry = &map.entries[map_index];
11083 const index = entry.acquire();
11084 if (index == .none) return null;
11085 if (entry.hash != hash) continue;
11086 if (names_items[@intFromEnum(index) - 1] == name) return index;
11087 }
11088 }
11089};
11090
11091pub fn getErrorValue(
11092 ip: *InternPool,
11093 gpa: Allocator,
11094 tid: Zcu.PerThread.Id,
11095 name: NullTerminatedString,
11096) Allocator.Error!Zcu.ErrorInt {
11097 return @intFromEnum(try ip.global_error_set.getErrorValue(gpa, &ip.getLocal(tid).mutate.arena, name));
11098}
11099
11100pub fn getErrorValueIfExists(ip: *const InternPool, name: NullTerminatedString) ?Zcu.ErrorInt {
11101 return @intFromEnum(ip.global_error_set.getErrorValueIfExists(name) orelse return null);
11102}
src/Sema.zig+17-14
...@@ -3473,7 +3473,7 @@ fn zirErrorSetDecl(...@@ -3473,7 +3473,7 @@ fn zirErrorSetDecl(
3473 const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);3473 const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
3474 const name = sema.code.nullTerminatedString(name_index);3474 const name = sema.code.nullTerminatedString(name_index);
3475 const name_ip = try mod.intern_pool.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);3475 const name_ip = try mod.intern_pool.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);
3476 _ = try mod.getErrorValue(name_ip);3476 _ = try pt.getErrorValue(name_ip);
3477 const result = names.getOrPutAssumeCapacity(name_ip);3477 const result = names.getOrPutAssumeCapacity(name_ip);
3478 assert(!result.found_existing); // verified in AstGen3478 assert(!result.found_existing); // verified in AstGen
3479 }3479 }
...@@ -8705,7 +8705,7 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -8705,7 +8705,7 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
8705 inst_data.get(sema.code),8705 inst_data.get(sema.code),
8706 .no_embedded_nulls,8706 .no_embedded_nulls,
8707 );8707 );
8708 _ = try pt.zcu.getErrorValue(name);8708 _ = try pt.getErrorValue(name);
8709 // Create an error set type with only this error value, and return the value.8709 // Create an error set type with only this error value, and return the value.
8710 const error_set_type = try pt.singleErrorSetType(name);8710 const error_set_type = try pt.singleErrorSetType(name);
8711 return Air.internedToRef((try pt.intern(.{ .err = .{8711 return Air.internedToRef((try pt.intern(.{ .err = .{
...@@ -8735,7 +8735,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8735,7 +8735,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8735 const err_name = ip.indexToKey(val.toIntern()).err.name;8735 const err_name = ip.indexToKey(val.toIntern()).err.name;
8736 return Air.internedToRef((try pt.intValue(8736 return Air.internedToRef((try pt.intValue(
8737 err_int_ty,8737 err_int_ty,
8738 try mod.getErrorValue(err_name),8738 try pt.getErrorValue(err_name),
8739 )).toIntern());8739 )).toIntern());
8740 }8740 }
87418741
...@@ -8746,10 +8746,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8746,10 +8746,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8746 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;8746 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
8747 switch (names.len) {8747 switch (names.len) {
8748 0 => return Air.internedToRef((try pt.intValue(err_int_ty, 0)).toIntern()),8748 0 => return Air.internedToRef((try pt.intValue(err_int_ty, 0)).toIntern()),
8749 1 => {8749 1 => return pt.intRef(err_int_ty, ip.getErrorValueIfExists(names.get(ip)[0]).?),
8750 const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?);
8751 return pt.intRef(err_int_ty, int);
8752 },
8753 else => {},8750 else => {},
8754 }8751 }
8755 },8752 },
...@@ -8765,6 +8762,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8765,6 +8762,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
87658762
8766 const pt = sema.pt;8763 const pt = sema.pt;
8767 const mod = pt.zcu;8764 const mod = pt.zcu;
8765 const ip = &mod.intern_pool;
8768 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;8766 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
8769 const src = block.nodeOffset(extra.node);8767 const src = block.nodeOffset(extra.node);
8770 const operand_src = block.builtinCallArgSrc(extra.node, 0);8768 const operand_src = block.builtinCallArgSrc(extra.node, 0);
...@@ -8774,11 +8772,16 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8774,11 +8772,16 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
87748772
8775 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {8773 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
8776 const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt));8774 const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt));
8777 if (int > mod.global_error_set.count() or int == 0)8775 if (int > len: {
8776 const mutate = &ip.global_error_set.mutate;
8777 mutate.mutex.lock();
8778 defer mutate.mutex.unlock();
8779 break :len mutate.list.len;
8780 } or int == 0)
8778 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});8781 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
8779 return Air.internedToRef((try pt.intern(.{ .err = .{8782 return Air.internedToRef((try pt.intern(.{ .err = .{
8780 .ty = .anyerror_type,8783 .ty = .anyerror_type,
8781 .name = mod.global_error_set.keys()[int],8784 .name = ip.global_error_set.shared.names.acquire().view().items(.@"0")[int - 1],
8782 } })));8785 } })));
8783 }8786 }
8784 try sema.requireRuntimeBlock(block, src, operand_src);8787 try sema.requireRuntimeBlock(block, src, operand_src);
...@@ -14005,7 +14008,7 @@ fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.R...@@ -14005,7 +14008,7 @@ fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.R
14005 inst_data.get(sema.code),14008 inst_data.get(sema.code),
14006 .no_embedded_nulls,14009 .no_embedded_nulls,
14007 );14010 );
14008 _ = try mod.getErrorValue(name);14011 _ = try pt.getErrorValue(name);
14009 const error_set_type = try pt.singleErrorSetType(name);14012 const error_set_type = try pt.singleErrorSetType(name);
14010 return Air.internedToRef((try pt.intern(.{ .err = .{14013 return Air.internedToRef((try pt.intern(.{ .err = .{
14011 .ty = error_set_type.toIntern(),14014 .ty = error_set_type.toIntern(),
...@@ -19564,7 +19567,7 @@ fn zirRetErrValue(...@@ -19564,7 +19567,7 @@ fn zirRetErrValue(
19564 inst_data.get(sema.code),19567 inst_data.get(sema.code),
19565 .no_embedded_nulls,19568 .no_embedded_nulls,
19566 );19569 );
19567 _ = try mod.getErrorValue(err_name);19570 _ = try pt.getErrorValue(err_name);
19568 // Return the error code from the function.19571 // Return the error code from the function.
19569 const error_set_type = try pt.singleErrorSetType(err_name);19572 const error_set_type = try pt.singleErrorSetType(err_name);
19570 const result_inst = Air.internedToRef((try pt.intern(.{ .err = .{19573 const result_inst = Air.internedToRef((try pt.intern(.{ .err = .{
...@@ -21607,7 +21610,7 @@ fn zirReify(...@@ -21607,7 +21610,7 @@ fn zirReify(
21607 const name = try sema.sliceToIpString(block, src, name_val, .{21610 const name = try sema.sliceToIpString(block, src, name_val, .{
21608 .needed_comptime_reason = "error set contents must be comptime-known",21611 .needed_comptime_reason = "error set contents must be comptime-known",
21609 });21612 });
21610 _ = try mod.getErrorValue(name);21613 _ = try pt.getErrorValue(name);
21611 const gop = names.getOrPutAssumeCapacity(name);21614 const gop = names.getOrPutAssumeCapacity(name);
21612 if (gop.found_existing) {21615 if (gop.found_existing) {
21613 return sema.fail(block, src, "duplicate error '{}'", .{21616 return sema.fail(block, src, "duplicate error '{}'", .{
...@@ -27485,7 +27488,7 @@ fn fieldVal(...@@ -27485,7 +27488,7 @@ fn fieldVal(
27485 },27488 },
27486 .simple_type => |t| {27489 .simple_type => |t| {
27487 assert(t == .anyerror);27490 assert(t == .anyerror);
27488 _ = try mod.getErrorValue(field_name);27491 _ = try pt.getErrorValue(field_name);
27489 },27492 },
27490 else => unreachable,27493 else => unreachable,
27491 }27494 }
...@@ -27725,7 +27728,7 @@ fn fieldPtr(...@@ -27725,7 +27728,7 @@ fn fieldPtr(
27725 },27728 },
27726 .simple_type => |t| {27729 .simple_type => |t| {
27727 assert(t == .anyerror);27730 assert(t == .anyerror);
27728 _ = try mod.getErrorValue(field_name);27731 _ = try pt.getErrorValue(field_name);
27729 },27732 },
27730 else => unreachable,27733 else => unreachable,
27731 }27734 }
src/Value.zig+5-5
...@@ -417,7 +417,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro...@@ -417,7 +417,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
417 var bigint_buffer: BigIntSpace = undefined;417 var bigint_buffer: BigIntSpace = undefined;
418 const bigint = BigIntMutable.init(418 const bigint = BigIntMutable.init(
419 &bigint_buffer.limbs,419 &bigint_buffer.limbs,
420 mod.global_error_set.getIndex(name).?,420 ip.getErrorValueIfExists(name).?,
421 ).toConst();421 ).toConst();
422 bigint.writeTwosComplement(buffer[0..byte_count], endian);422 bigint.writeTwosComplement(buffer[0..byte_count], endian);
423 },423 },
...@@ -427,7 +427,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro...@@ -427,7 +427,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
427 if (val.unionTag(mod)) |union_tag| {427 if (val.unionTag(mod)) |union_tag| {
428 const union_obj = mod.typeToUnion(ty).?;428 const union_obj = mod.typeToUnion(ty).?;
429 const field_index = mod.unionTagFieldIndex(union_obj, union_tag).?;429 const field_index = mod.unionTagFieldIndex(union_obj, union_tag).?;
430 const field_type = Type.fromInterned(union_obj.field_types.get(&mod.intern_pool)[field_index]);430 const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
431 const field_val = try val.fieldValue(pt, field_index);431 const field_val = try val.fieldValue(pt, field_index);
432 const byte_count: usize = @intCast(field_type.abiSize(pt));432 const byte_count: usize = @intCast(field_type.abiSize(pt));
433 return writeToMemory(field_val, field_type, pt, buffer[0..byte_count]);433 return writeToMemory(field_val, field_type, pt, buffer[0..byte_count]);
...@@ -1455,9 +1455,9 @@ pub fn getErrorName(val: Value, mod: *const Module) InternPool.OptionalNullTermi...@@ -1455,9 +1455,9 @@ pub fn getErrorName(val: Value, mod: *const Module) InternPool.OptionalNullTermi
1455 };1455 };
1456}1456}
14571457
1458pub fn getErrorInt(val: Value, mod: *const Module) Module.ErrorInt {1458pub fn getErrorInt(val: Value, zcu: *Zcu) Module.ErrorInt {
1459 return if (getErrorName(val, mod).unwrap()) |err_name|1459 return if (getErrorName(val, zcu).unwrap()) |err_name|
1460 @intCast(mod.global_error_set.getIndex(err_name).?)1460 zcu.intern_pool.getErrorValueIfExists(err_name).?
1461 else1461 else
1462 0;1462 0;
1463}1463}
src/Zcu.zig-22
...@@ -141,9 +141,6 @@ failed_exports: std.AutoArrayHashMapUnmanaged(u32, *ErrorMsg) = .{},...@@ -141,9 +141,6 @@ failed_exports: std.AutoArrayHashMapUnmanaged(u32, *ErrorMsg) = .{},
141/// are stored here.141/// are stored here.
142cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = .{},142cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = .{},
143143
144/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
145global_error_set: GlobalErrorSet = .{},
146
147/// Maximum amount of distinct error values, set by --error-limit144/// Maximum amount of distinct error values, set by --error-limit
148error_limit: ErrorInt,145error_limit: ErrorInt,
149146
...@@ -2399,7 +2396,6 @@ pub const CompileError = error{...@@ -2399,7 +2396,6 @@ pub const CompileError = error{
2399pub fn init(mod: *Module, thread_count: usize) !void {2396pub fn init(mod: *Module, thread_count: usize) !void {
2400 const gpa = mod.gpa;2397 const gpa = mod.gpa;
2401 try mod.intern_pool.init(gpa, thread_count);2398 try mod.intern_pool.init(gpa, thread_count);
2402 try mod.global_error_set.put(gpa, .empty, {});
2403}2399}
24042400
2405pub fn deinit(zcu: *Zcu) void {2401pub fn deinit(zcu: *Zcu) void {
...@@ -2471,8 +2467,6 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2471,8 +2467,6 @@ pub fn deinit(zcu: *Zcu) void {
2471 zcu.single_exports.deinit(gpa);2467 zcu.single_exports.deinit(gpa);
2472 zcu.multi_exports.deinit(gpa);2468 zcu.multi_exports.deinit(gpa);
24732469
2474 zcu.global_error_set.deinit(gpa);
2475
2476 zcu.potentially_outdated.deinit(gpa);2470 zcu.potentially_outdated.deinit(gpa);
2477 zcu.outdated.deinit(gpa);2471 zcu.outdated.deinit(gpa);
2478 zcu.outdated_ready.deinit(gpa);2472 zcu.outdated_ready.deinit(gpa);
...@@ -3108,22 +3102,6 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit...@@ -3108,22 +3102,6 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit
3108 gop.value_ptr.* = @intCast(ref_idx);3102 gop.value_ptr.* = @intCast(ref_idx);
3109}3103}
31103104
3111pub fn getErrorValue(
3112 mod: *Module,
3113 name: InternPool.NullTerminatedString,
3114) Allocator.Error!ErrorInt {
3115 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
3116 return @as(ErrorInt, @intCast(gop.index));
3117}
3118
3119pub fn getErrorValueFromSlice(
3120 mod: *Module,
3121 name: []const u8,
3122) Allocator.Error!ErrorInt {
3123 const interned_name = try mod.intern_pool.getOrPutString(mod.gpa, name);
3124 return getErrorValue(mod, interned_name);
3125}
3126
3127pub fn errorSetBits(mod: *Module) u16 {3105pub fn errorSetBits(mod: *Module) u16 {
3128 if (mod.error_limit == 0) return 0;3106 if (mod.error_limit == 0) return 0;
3129 return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error3107 return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error
src/Zcu/PerThread.zig+11
...@@ -2287,6 +2287,17 @@ pub fn allocateNewDecl(pt: Zcu.PerThread, namespace: Zcu.Namespace.Index) !Zcu.D...@@ -2287,6 +2287,17 @@ pub fn allocateNewDecl(pt: Zcu.PerThread, namespace: Zcu.Namespace.Index) !Zcu.D
2287 return decl_index;2287 return decl_index;
2288}2288}
22892289
2290pub fn getErrorValue(
2291 pt: Zcu.PerThread,
2292 name: InternPool.NullTerminatedString,
2293) Allocator.Error!Zcu.ErrorInt {
2294 return pt.zcu.intern_pool.getErrorValue(pt.zcu.gpa, pt.tid, name);
2295}
2296
2297pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Zcu.ErrorInt {
2298 return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, name));
2299}
2300
2290pub fn initNewAnonDecl(2301pub fn initNewAnonDecl(
2291 pt: Zcu.PerThread,2302 pt: Zcu.PerThread,
2292 new_decl_index: Zcu.Decl.Index,2303 new_decl_index: Zcu.Decl.Index,
src/arch/wasm/CodeGen.zig+9-14
...@@ -3304,7 +3304,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {...@@ -3304,7 +3304,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
3304 }3304 }
3305 },3305 },
3306 .err => |err| {3306 .err => |err| {
3307 const int = try mod.getErrorValue(err.name);3307 const int = try pt.getErrorValue(err.name);
3308 return WValue{ .imm32 = int };3308 return WValue{ .imm32 = int };
3309 },3309 },
3310 .error_union => |error_union| {3310 .error_union => |error_union| {
...@@ -3452,30 +3452,25 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {...@@ -3452,30 +3452,25 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
3452/// Returns a `Value` as a signed 32 bit value.3452/// Returns a `Value` as a signed 32 bit value.
3453/// It's illegal to provide a value with a type that cannot be represented3453/// It's illegal to provide a value with a type that cannot be represented
3454/// as an integer value.3454/// as an integer value.
3455fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {3455fn valueAsI32(func: *const CodeGen, val: Value) i32 {
3456 const pt = func.pt;3456 const pt = func.pt;
3457 const mod = pt.zcu;3457 const mod = pt.zcu;
3458 const ip = &mod.intern_pool;
34583459
3459 switch (val.ip_index) {3460 switch (val.toIntern()) {
3460 .none => {},
3461 .bool_true => return 1,3461 .bool_true => return 1,
3462 .bool_false => return 0,3462 .bool_false => return 0,
3463 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {3463 else => return switch (ip.indexToKey(val.ip_index)) {
3464 .enum_tag => |enum_tag| intIndexAsI32(&mod.intern_pool, enum_tag.int, pt),3464 .enum_tag => |enum_tag| intIndexAsI32(ip, enum_tag.int, pt),
3465 .int => |int| intStorageAsI32(int.storage, pt),3465 .int => |int| intStorageAsI32(int.storage, pt),
3466 .ptr => |ptr| {3466 .ptr => |ptr| {
3467 assert(ptr.base_addr == .int);3467 assert(ptr.base_addr == .int);
3468 return @intCast(ptr.byte_offset);3468 return @intCast(ptr.byte_offset);
3469 },3469 },
3470 .err => |err| @as(i32, @bitCast(@as(Zcu.ErrorInt, @intCast(mod.global_error_set.getIndex(err.name).?)))),3470 .err => |err| @bitCast(ip.getErrorValueIfExists(err.name).?),
3471 else => unreachable,3471 else => unreachable,
3472 },3472 },
3473 }3473 }
3474
3475 return switch (ty.zigTypeTag(mod)) {
3476 .ErrorSet => @as(i32, @bitCast(val.getErrorInt(mod))),
3477 else => unreachable, // Programmer called this function for an illegal type
3478 };
3479}3474}
34803475
3481fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index, pt: Zcu.PerThread) i32 {3476fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index, pt: Zcu.PerThread) i32 {
...@@ -4098,7 +4093,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -4098,7 +4093,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
40984093
4099 for (items, 0..) |ref, i| {4094 for (items, 0..) |ref, i| {
4100 const item_val = (try func.air.value(ref, pt)).?;4095 const item_val = (try func.air.value(ref, pt)).?;
4101 const int_val = func.valueAsI32(item_val, target_ty);4096 const int_val = func.valueAsI32(item_val);
4102 if (lowest_maybe == null or int_val < lowest_maybe.?) {4097 if (lowest_maybe == null or int_val < lowest_maybe.?) {
4103 lowest_maybe = int_val;4098 lowest_maybe = int_val;
4104 }4099 }
...@@ -7454,7 +7449,7 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -7454,7 +7449,7 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7454 var lowest: ?u32 = null;7449 var lowest: ?u32 = null;
7455 var highest: ?u32 = null;7450 var highest: ?u32 = null;
7456 for (0..names.len) |name_index| {7451 for (0..names.len) |name_index| {
7457 const err_int: Zcu.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[name_index]).?);7452 const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;
7458 if (lowest) |*l| {7453 if (lowest) |*l| {
7459 if (err_int < l.*) {7454 if (err_int < l.*) {
7460 l.* = err_int;7455 l.* = err_int;
src/arch/x86_64/CodeGen.zig+2-2
...@@ -16435,7 +16435,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -16435,7 +16435,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
16435 .size = .dword,16435 .size = .dword,
16436 .index = err_reg.to64(),16436 .index = err_reg.to64(),
16437 .scale = .@"4",16437 .scale = .@"4",
16438 .disp = 4,16438 .disp = (1 - 1) * 4,
16439 } },16439 } },
16440 },16440 },
16441 );16441 );
...@@ -16448,7 +16448,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {...@@ -16448,7 +16448,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
16448 .size = .dword,16448 .size = .dword,
16449 .index = err_reg.to64(),16449 .index = err_reg.to64(),
16450 .scale = .@"4",16450 .scale = .@"4",
16451 .disp = 8,16451 .disp = (2 - 1) * 4,
16452 } },16452 } },
16453 },16453 },
16454 );16454 );
src/codegen.zig+5-5
...@@ -137,10 +137,10 @@ pub fn generateLazySymbol(...@@ -137,10 +137,10 @@ pub fn generateLazySymbol(
137137
138 if (lazy_sym.ty.isAnyError(pt.zcu)) {138 if (lazy_sym.ty.isAnyError(pt.zcu)) {
139 alignment.* = .@"4";139 alignment.* = .@"4";
140 const err_names = pt.zcu.global_error_set.keys();140 const err_names = ip.global_error_set.getNamesFromMainThread();
141 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(err_names.len), endian);141 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(err_names.len), endian);
142 var offset = code.items.len;142 var offset = code.items.len;
143 try code.resize((1 + err_names.len + 1) * 4);143 try code.resize((err_names.len + 1) * 4);
144 for (err_names) |err_name_nts| {144 for (err_names) |err_name_nts| {
145 const err_name = err_name_nts.toSlice(ip);145 const err_name = err_name_nts.toSlice(ip);
146 mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian);146 mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian);
...@@ -243,13 +243,13 @@ pub fn generateSymbol(...@@ -243,13 +243,13 @@ pub fn generateSymbol(
243 int_val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian);243 int_val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian);
244 },244 },
245 .err => |err| {245 .err => |err| {
246 const int = try mod.getErrorValue(err.name);246 const int = try pt.getErrorValue(err.name);
247 try code.writer().writeInt(u16, @intCast(int), endian);247 try code.writer().writeInt(u16, @intCast(int), endian);
248 },248 },
249 .error_union => |error_union| {249 .error_union => |error_union| {
250 const payload_ty = ty.errorUnionPayload(mod);250 const payload_ty = ty.errorUnionPayload(mod);
251 const err_val: u16 = switch (error_union.val) {251 const err_val: u16 = switch (error_union.val) {
252 .err_name => |err_name| @intCast(try mod.getErrorValue(err_name)),252 .err_name => |err_name| @intCast(try pt.getErrorValue(err_name)),
253 .payload => 0,253 .payload => 0,
254 };254 };
255255
...@@ -1058,7 +1058,7 @@ pub fn genTypedValue(...@@ -1058,7 +1058,7 @@ pub fn genTypedValue(
1058 },1058 },
1059 .ErrorSet => {1059 .ErrorSet => {
1060 const err_name = ip.indexToKey(val.toIntern()).err.name;1060 const err_name = ip.indexToKey(val.toIntern()).err.name;
1061 const error_index = zcu.global_error_set.getIndex(err_name).?;1061 const error_index = try pt.getErrorValue(err_name);
1062 return GenResult.mcv(.{ .immediate = error_index });1062 return GenResult.mcv(.{ .immediate = error_index });
1063 },1063 },
1064 .ErrorUnion => {1064 .ErrorUnion => {
src/codegen/c.zig+8-7
...@@ -2622,10 +2622,11 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2622,10 +2622,11 @@ pub fn genErrDecls(o: *Object) !void {
26222622
2623 var max_name_len: usize = 0;2623 var max_name_len: usize = 0;
2624 // do not generate an invalid empty enum when the global error set is empty2624 // do not generate an invalid empty enum when the global error set is empty
2625 if (zcu.global_error_set.keys().len > 1) {2625 const names = ip.global_error_set.getNamesFromMainThread();
2626 if (names.len > 0) {
2626 try writer.writeAll("enum {\n");2627 try writer.writeAll("enum {\n");
2627 o.indent_writer.pushIndent();2628 o.indent_writer.pushIndent();
2628 for (zcu.global_error_set.keys()[1..], 1..) |name_nts, value| {2629 for (names, 1..) |name_nts, value| {
2629 const name = name_nts.toSlice(ip);2630 const name = name_nts.toSlice(ip);
2630 max_name_len = @max(name.len, max_name_len);2631 max_name_len = @max(name.len, max_name_len);
2631 const err_val = try pt.intern(.{ .err = .{2632 const err_val = try pt.intern(.{ .err = .{
...@@ -2644,7 +2645,7 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2644,7 +2645,7 @@ pub fn genErrDecls(o: *Object) !void {
2644 defer o.dg.gpa.free(name_buf);2645 defer o.dg.gpa.free(name_buf);
26452646
2646 @memcpy(name_buf[0..name_prefix.len], name_prefix);2647 @memcpy(name_buf[0..name_prefix.len], name_prefix);
2647 for (zcu.global_error_set.keys()) |name| {2648 for (names) |name| {
2648 const name_slice = name.toSlice(ip);2649 const name_slice = name.toSlice(ip);
2649 @memcpy(name_buf[name_prefix.len..][0..name_slice.len], name_slice);2650 @memcpy(name_buf[name_prefix.len..][0..name_slice.len], name_slice);
2650 const identifier = name_buf[0 .. name_prefix.len + name_slice.len];2651 const identifier = name_buf[0 .. name_prefix.len + name_slice.len];
...@@ -2674,7 +2675,7 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2674,7 +2675,7 @@ pub fn genErrDecls(o: *Object) !void {
2674 }2675 }
26752676
2676 const name_array_ty = try pt.arrayType(.{2677 const name_array_ty = try pt.arrayType(.{
2677 .len = zcu.global_error_set.count(),2678 .len = 1 + names.len,
2678 .child = .slice_const_u8_sentinel_0_type,2679 .child = .slice_const_u8_sentinel_0_type,
2679 });2680 });
26802681
...@@ -2688,9 +2689,9 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2688,9 +2689,9 @@ pub fn genErrDecls(o: *Object) !void {
2688 .complete,2689 .complete,
2689 );2690 );
2690 try writer.writeAll(" = {");2691 try writer.writeAll(" = {");
2691 for (zcu.global_error_set.keys(), 0..) |name_nts, value| {2692 for (names, 1..) |name_nts, val| {
2692 const name = name_nts.toSlice(ip);2693 const name = name_nts.toSlice(ip);
2693 if (value != 0) try writer.writeByte(',');2694 if (val > 1) try writer.writeAll(", ");
2694 try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{2695 try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
2695 fmtIdent(name),2696 fmtIdent(name),
2696 try o.dg.fmtIntLiteral(try pt.intValue(Type.usize, name.len), .StaticInitializer),2697 try o.dg.fmtIntLiteral(try pt.intValue(Type.usize, name.len), .StaticInitializer),
...@@ -6873,7 +6874,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6873,7 +6874,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
68736874
6874 try writer.writeAll(" = zig_errorName[");6875 try writer.writeAll(" = zig_errorName[");
6875 try f.writeCValue(writer, operand, .Other);6876 try f.writeCValue(writer, operand, .Other);
6876 try writer.writeAll("];\n");6877 try writer.writeAll(" - 1];\n");
6877 return local;6878 return local;
6878}6879}
68796880
src/codegen/llvm.zig+11-10
...@@ -1036,20 +1036,21 @@ pub const Object = struct {...@@ -1036,20 +1036,21 @@ pub const Object = struct {
10361036
1037 const pt = o.pt;1037 const pt = o.pt;
1038 const mod = pt.zcu;1038 const mod = pt.zcu;
1039 const ip = &mod.intern_pool;
10391040
1040 const error_name_list = mod.global_error_set.keys();1041 const error_name_list = ip.global_error_set.getNamesFromMainThread();
1041 const llvm_errors = try mod.gpa.alloc(Builder.Constant, error_name_list.len);1042 const llvm_errors = try mod.gpa.alloc(Builder.Constant, 1 + error_name_list.len);
1042 defer mod.gpa.free(llvm_errors);1043 defer mod.gpa.free(llvm_errors);
10431044
1044 // TODO: Address space1045 // TODO: Address space
1045 const slice_ty = Type.slice_const_u8_sentinel_0;1046 const slice_ty = Type.slice_const_u8_sentinel_0;
1046 const llvm_usize_ty = try o.lowerType(Type.usize);1047 const llvm_usize_ty = try o.lowerType(Type.usize);
1047 const llvm_slice_ty = try o.lowerType(slice_ty);1048 const llvm_slice_ty = try o.lowerType(slice_ty);
1048 const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty);1049 const llvm_table_ty = try o.builder.arrayType(1 + error_name_list.len, llvm_slice_ty);
10491050
1050 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);1051 llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
1051 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {1052 for (llvm_errors[1..], error_name_list) |*llvm_error, name| {
1052 const name_string = try o.builder.stringNull(name.toSlice(&mod.intern_pool));1053 const name_string = try o.builder.stringNull(name.toSlice(ip));
1053 const name_init = try o.builder.stringConst(name_string);1054 const name_init = try o.builder.stringConst(name_string);
1054 const name_variable_index =1055 const name_variable_index =
1055 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);1056 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
...@@ -1085,7 +1086,7 @@ pub const Object = struct {...@@ -1085,7 +1086,7 @@ pub const Object = struct {
1085 // If there is no such function in the module, it means the source code does not need it.1086 // If there is no such function in the module, it means the source code does not need it.
1086 const name = o.builder.strtabStringIfExists(lt_errors_fn_name) orelse return;1087 const name = o.builder.strtabStringIfExists(lt_errors_fn_name) orelse return;
1087 const llvm_fn = o.builder.getGlobal(name) orelse return;1088 const llvm_fn = o.builder.getGlobal(name) orelse return;
1088 const errors_len = o.pt.zcu.global_error_set.count();1089 const errors_len = o.pt.zcu.intern_pool.global_error_set.mutate.list.len;
10891090
1090 var wip = try Builder.WipFunction.init(&o.builder, .{1091 var wip = try Builder.WipFunction.init(&o.builder, .{
1091 .function = llvm_fn.ptrConst(&o.builder).kind.function,1092 .function = llvm_fn.ptrConst(&o.builder).kind.function,
...@@ -1096,12 +1097,12 @@ pub const Object = struct {...@@ -1096,12 +1097,12 @@ pub const Object = struct {
10961097
1097 // Example source of the following LLVM IR:1098 // Example source of the following LLVM IR:
1098 // fn __zig_lt_errors_len(index: u16) bool {1099 // fn __zig_lt_errors_len(index: u16) bool {
1099 // return index < total_errors_len;1100 // return index <= total_errors_len;
1100 // }1101 // }
11011102
1102 const lhs = wip.arg(0);1103 const lhs = wip.arg(0);
1103 const rhs = try o.builder.intValue(try o.errorIntType(), errors_len);1104 const rhs = try o.builder.intValue(try o.errorIntType(), errors_len);
1104 const is_lt = try wip.icmp(.ult, lhs, rhs, "");1105 const is_lt = try wip.icmp(.ule, lhs, rhs, "");
1105 _ = try wip.ret(is_lt);1106 _ = try wip.ret(is_lt);
1106 try wip.finish();1107 try wip.finish();
1107 }1108 }
...@@ -3820,7 +3821,7 @@ pub const Object = struct {...@@ -3820,7 +3821,7 @@ pub const Object = struct {
3820 return lowerBigInt(o, ty, bigint);3821 return lowerBigInt(o, ty, bigint);
3821 },3822 },
3822 .err => |err| {3823 .err => |err| {
3823 const int = try mod.getErrorValue(err.name);3824 const int = try pt.getErrorValue(err.name);
3824 const llvm_int = try o.builder.intConst(try o.errorIntType(), int);3825 const llvm_int = try o.builder.intConst(try o.errorIntType(), int);
3825 return llvm_int;3826 return llvm_int;
3826 },3827 },
...@@ -9658,7 +9659,7 @@ pub const FuncGen = struct {...@@ -9658,7 +9659,7 @@ pub const FuncGen = struct {
9658 defer wip_switch.finish(&self.wip);9659 defer wip_switch.finish(&self.wip);
96599660
9660 for (0..names.len) |name_index| {9661 for (0..names.len) |name_index| {
9661 const err_int = mod.global_error_set.getIndex(names.get(ip)[name_index]).?;9662 const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;
9662 const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int);9663 const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int);
9663 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);9664 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
9664 }9665 }
src/codegen/spirv.zig+1-1
...@@ -963,7 +963,7 @@ const DeclGen = struct {...@@ -963,7 +963,7 @@ const DeclGen = struct {
963 break :cache result_id;963 break :cache result_id;
964 },964 },
965 .err => |err| {965 .err => |err| {
966 const value = try mod.getErrorValue(err.name);966 const value = try pt.getErrorValue(err.name);
967 break :cache try self.constInt(ty, value, repr);967 break :cache try self.constInt(ty, value, repr);
968 },968 },
969 .error_union => |error_union| {969 .error_union => |error_union| {
src/link/Dwarf.zig+2-2
...@@ -2698,7 +2698,7 @@ pub fn flushModule(self: *Dwarf, pt: Zcu.PerThread) !void {...@@ -2698,7 +2698,7 @@ pub fn flushModule(self: *Dwarf, pt: Zcu.PerThread) !void {
2698 try addDbgInfoErrorSetNames(2698 try addDbgInfoErrorSetNames(
2699 pt,2699 pt,
2700 Type.anyerror,2700 Type.anyerror,
2701 pt.zcu.global_error_set.keys(),2701 pt.zcu.intern_pool.global_error_set.getNamesFromMainThread(),
2702 target,2702 target,
2703 &dbg_info_buffer,2703 &dbg_info_buffer,
2704 );2704 );
...@@ -2867,7 +2867,7 @@ fn addDbgInfoErrorSetNames(...@@ -2867,7 +2867,7 @@ fn addDbgInfoErrorSetNames(
2867 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);2867 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
28682868
2869 for (error_names) |error_name| {2869 for (error_names) |error_name| {
2870 const int = try pt.zcu.getErrorValue(error_name);2870 const int = try pt.getErrorValue(error_name);
2871 const error_name_slice = error_name.toSlice(&pt.zcu.intern_pool);2871 const error_name_slice = error_name.toSlice(&pt.zcu.intern_pool);
2872 // DW.AT.enumerator2872 // DW.AT.enumerator
2873 try dbg_info_buffer.ensureUnusedCapacity(error_name_slice.len + 2 + @sizeOf(u64));2873 try dbg_info_buffer.ensureUnusedCapacity(error_name_slice.len + 2 + @sizeOf(u64));
src/link/SpirV.zig+4-4
...@@ -227,9 +227,9 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n...@@ -227,9 +227,9 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
227 var error_info = std.ArrayList(u8).init(self.object.gpa);227 var error_info = std.ArrayList(u8).init(self.object.gpa);
228 defer error_info.deinit();228 defer error_info.deinit();
229229
230 try error_info.appendSlice("zig_errors");230 try error_info.appendSlice("zig_errors:");
231 const mod = self.base.comp.module.?;231 const ip = &self.base.comp.module.?.intern_pool;
232 for (mod.global_error_set.keys()) |name| {232 for (ip.global_error_set.getNamesFromMainThread()) |name| {
233 // Errors can contain pretty much any character - to encode them in a string we must escape233 // Errors can contain pretty much any character - to encode them in a string we must escape
234 // them somehow. Easiest here is to use some established scheme, one which also preseves the234 // them somehow. Easiest here is to use some established scheme, one which also preseves the
235 // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.235 // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.
...@@ -238,7 +238,7 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n...@@ -238,7 +238,7 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
238 try error_info.append(':');238 try error_info.append(':');
239 try std.Uri.Component.percentEncode(239 try std.Uri.Component.percentEncode(
240 error_info.writer(),240 error_info.writer(),
241 name.toSlice(&mod.intern_pool),241 name.toSlice(ip),
242 struct {242 struct {
243 fn isValidChar(c: u8) bool {243 fn isValidChar(c: u8) bool {
244 return switch (c) {244 return switch (c) {
src/link/Wasm/ZigObject.zig+15-6
...@@ -652,13 +652,22 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm, tid: Zcu.Per...@@ -652,13 +652,22 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm, tid: Zcu.Per
652 // Addend for each relocation to the table652 // Addend for each relocation to the table
653 var addend: u32 = 0;653 var addend: u32 = 0;
654 const pt: Zcu.PerThread = .{ .zcu = wasm_file.base.comp.module.?, .tid = tid };654 const pt: Zcu.PerThread = .{ .zcu = wasm_file.base.comp.module.?, .tid = tid };
655 for (pt.zcu.global_error_set.keys()) |error_name| {655 const slice_ty = Type.slice_const_u8_sentinel_0;
656 const atom = wasm_file.getAtomPtr(atom_index);656 const atom = wasm_file.getAtomPtr(atom_index);
657 {
658 // TODO: remove this unreachable entry
659 try atom.code.appendNTimes(gpa, 0, 4);
660 try atom.code.writer(gpa).writeInt(u32, 0, .little);
661 atom.size += @intCast(slice_ty.abiSize(pt));
662 addend += 1;
657663
658 const error_name_slice = error_name.toSlice(&pt.zcu.intern_pool);664 try names_atom.code.append(gpa, 0);
665 }
666 const ip = &pt.zcu.intern_pool;
667 for (ip.global_error_set.getNamesFromMainThread()) |error_name| {
668 const error_name_slice = error_name.toSlice(ip);
659 const len: u32 = @intCast(error_name_slice.len + 1); // names are 0-terminated669 const len: u32 = @intCast(error_name_slice.len + 1); // names are 0-terminated
660670
661 const slice_ty = Type.slice_const_u8_sentinel_0;
662 const offset = @as(u32, @intCast(atom.code.items.len));671 const offset = @as(u32, @intCast(atom.code.items.len));
663 // first we create the data for the slice of the name672 // first we create the data for the slice of the name
664 try atom.code.appendNTimes(gpa, 0, 4); // ptr to name, will be relocated673 try atom.code.appendNTimes(gpa, 0, 4); // ptr to name, will be relocated
...@@ -677,7 +686,7 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm, tid: Zcu.Per...@@ -677,7 +686,7 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm, tid: Zcu.Per
677 try names_atom.code.ensureUnusedCapacity(gpa, len);686 try names_atom.code.ensureUnusedCapacity(gpa, len);
678 names_atom.code.appendSliceAssumeCapacity(error_name_slice[0..len]);687 names_atom.code.appendSliceAssumeCapacity(error_name_slice[0..len]);
679688
680 log.debug("Populated error name: '{}'", .{error_name.fmt(&pt.zcu.intern_pool)});689 log.debug("Populated error name: '{}'", .{error_name.fmt(ip)});
681 }690 }
682 names_atom.size = addend;691 names_atom.size = addend;
683 zig_object.error_names_atom = names_atom_index;692 zig_object.error_names_atom = names_atom_index;
...@@ -1042,7 +1051,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {...@@ -1042,7 +1051,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {
1042 const gpa = wasm_file.base.comp.gpa;1051 const gpa = wasm_file.base.comp.gpa;
1043 const sym_index = zig_object.findGlobalSymbol("__zig_errors_len") orelse return;1052 const sym_index = zig_object.findGlobalSymbol("__zig_errors_len") orelse return;
10441053
1045 const errors_len = wasm_file.base.comp.module.?.global_error_set.count();1054 const errors_len = 1 + wasm_file.base.comp.module.?.intern_pool.global_error_set.mutate.list.len;
1046 // overwrite existing atom if it already exists (maybe the error set has increased)1055 // overwrite existing atom if it already exists (maybe the error set has increased)
1047 // if not, allcoate a new atom.1056 // if not, allcoate a new atom.
1048 const atom_index = if (wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = sym_index })) |index| blk: {1057 const atom_index = if (wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = sym_index })) |index| blk: {