authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-23 03:19:03-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-10-23 03:19:03-04:00
log94d61ce964cd23fcf46dabeddc19837b4dd3209f
tree00fc6af0a362d7d5744744e3f5e8008136957401
parentb82459fa435c366c6af0fee96c3d9b95c24078f9
parented82e4f7ac057286444135dda79fb7c6a579573a
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17651 from Vexu/error-limit

Make distinct error limit configurable (attempt #2)

14 files changed, 195 insertions(+), 110 deletions(-)

doc/langref.html.in+5-4
......@@ -5373,8 +5373,9 @@ test "fn reflection" {
53735373 gets assigned the same integer value.
53745374 </p>
53755375 <p>
5376 The number of unique error values across the entire compilation should determine the size of the error set type.
5377 However right now it is hard coded to be a {#syntax#}u16{#endsyntax#}. See <a href="https://github.com/ziglang/zig/issues/786">#786</a>.
5376 The error set type defaults to a {#syntax#}u16{#endsyntax#}, though if the maximum number of distinct
5377 error values is provided via the <kbd>--error-limit [num]</kbd> command line parameter an integer type
5378 with the minimum number of bits required to represent all of the error values will be used.
53785379 </p>
53795380 <p>
53805381 You can {#link|coerce|Type Coercion#} an error from a subset to a superset:
......@@ -8373,7 +8374,7 @@ test "main" {
83738374 {#header_close#}
83748375
83758376 {#header_open|@errorFromInt#}
8376 <pre>{#syntax#}@errorFromInt(value: std.meta.Int(.unsigned, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre>
8377 <pre>{#syntax#}@errorFromInt(value: std.meta.Int(.unsigned, @bitSizeOf(anyerror))) anyerror{#endsyntax#}</pre>
83778378 <p>
83788379 Converts from the integer representation of an error into {#link|The Global Error Set#} type.
83798380 </p>
......@@ -8694,7 +8695,7 @@ test "integer cast panic" {
86948695 {#header_close#}
86958696
86968697 {#header_open|@intFromError#}
8697 <pre>{#syntax#}@intFromError(err: anytype) std.meta.Int(.unsigned, @sizeOf(anyerror) * 8){#endsyntax#}</pre>
8698 <pre>{#syntax#}@intFromError(err: anytype) std.meta.Int(.unsigned, @bitSizeOf(anyerror)){#endsyntax#}</pre>
86988699 <p>
86998700 Supports the following types:
87008701 </p>
src/AstGen.zig+1-1
......@@ -8432,7 +8432,7 @@ fn builtinCall(
84328432 return rvalue(gz, ri, result, node);
84338433 },
84348434 .error_from_int => {
8435 const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[0]);
8435 const operand = try expr(gz, scope, .{ .rl = .none }, params[0]);
84368436 const result = try gz.addExtendedPayload(.error_from_int, Zir.Inst.UnNode{
84378437 .node = gz.nodeIndexToRelative(node),
84388438 .operand = operand,
src/Compilation.zig+23
......@@ -739,6 +739,7 @@ pub const InitOptions = struct {
739739 pdb_source_path: ?[]const u8 = null,
740740 /// (Windows) PDB output path
741741 pdb_out_path: ?[]const u8 = null,
742 error_limit: ?Module.ErrorInt = null,
742743};
743744
744745fn addModuleTableToCacheHash(
......@@ -1432,6 +1433,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14321433 .local_zir_cache = local_zir_cache,
14331434 .emit_h = emit_h,
14341435 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
1436 .error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1),
14351437 };
14361438 try module.init();
14371439
......@@ -2486,6 +2488,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
24862488 man.hash.add(comp.bin_file.options.skip_linker_dependencies);
24872489 man.hash.add(comp.bin_file.options.parent_compilation_link_libc);
24882490 man.hash.add(mod.emit_h != null);
2491 man.hash.add(mod.error_limit);
24892492 }
24902493
24912494 try man.addOptionalFile(comp.bin_file.options.linker_script);
......@@ -2866,6 +2869,10 @@ pub fn totalErrorCount(self: *Compilation) u32 {
28662869 }
28672870 }
28682871 }
2872
2873 if (module.global_error_set.entries.len - 1 > module.error_limit) {
2874 total += 1;
2875 }
28692876 }
28702877
28712878 // The "no entry point found" error only counts if there are no semantic analysis errors.
......@@ -3016,6 +3023,22 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
30163023 for (module.failed_exports.values()) |value| {
30173024 try addModuleErrorMsg(module, &bundle, value.*);
30183025 }
3026
3027 const actual_error_count = module.global_error_set.entries.len - 1;
3028 if (actual_error_count > module.error_limit) {
3029 try bundle.addRootErrorMessage(.{
3030 .msg = try bundle.printString("module used more errors than possible: used {d}, max {d}", .{
3031 actual_error_count, module.error_limit,
3032 }),
3033 .notes_len = 1,
3034 });
3035 const notes_start = try bundle.reserveNotes(1);
3036 bundle.extra.items[notes_start] = @intFromEnum(try bundle.addErrorMessage(.{
3037 .msg = try bundle.printString("use '--error-limit {d}' to increase limit", .{
3038 actual_error_count,
3039 }),
3040 }));
3041 }
30193042 }
30203043
30213044 if (bundle.root_list.items.len == 0) {
src/Module.zig+12
......@@ -137,6 +137,9 @@ deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
137137/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
138138global_error_set: GlobalErrorSet = .{},
139139
140/// Maximum amount of distinct error values, set by --error-limit
141error_limit: ErrorInt,
142
140143/// Incrementing integer used to compare against the corresponding Decl
141144/// field to determine whether a Decl's status applies to an ongoing update, or a
142145/// previous analysis.
......@@ -5020,6 +5023,11 @@ pub fn getErrorValueFromSlice(
50205023 return getErrorValue(mod, interned_name);
50215024}
50225025
5026pub fn errorSetBits(mod: *Module) u16 {
5027 if (mod.error_limit == 0) return 0;
5028 return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error
5029}
5030
50235031pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {
50245032 const src_decl = mod.declPtr(block.src_decl);
50255033 return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value);
......@@ -5898,6 +5906,10 @@ pub fn intType(mod: *Module, signedness: std.builtin.Signedness, bits: u16) Allo
58985906 } })).toType();
58995907}
59005908
5909pub fn errorIntType(mod: *Module) std.mem.Allocator.Error!Type {
5910 return mod.intType(.unsigned, mod.errorSetBits());
5911}
5912
59015913pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type {
59025914 const i = try intern(mod, .{ .array_type = info });
59035915 return i.toType();
src/Sema.zig+12-9
......@@ -8404,14 +8404,15 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
84048404 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
84058405 const uncasted_operand = try sema.resolveInst(extra.operand);
84068406 const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src);
8407 const err_int_ty = try mod.errorIntType();
84078408
84088409 if (try sema.resolveMaybeUndefVal(operand)) |val| {
84098410 if (val.isUndef(mod)) {
8410 return mod.undefRef(Type.err_int);
8411 return mod.undefRef(err_int_ty);
84118412 }
84128413 const err_name = ip.indexToKey(val.toIntern()).err.name;
84138414 return Air.internedToRef((try mod.intValue(
8414 Type.err_int,
8415 err_int_ty,
84158416 try mod.getErrorValue(err_name),
84168417 )).toIntern());
84178418 }
......@@ -8422,10 +8423,10 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
84228423 else => |err_set_ty_index| {
84238424 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
84248425 switch (names.len) {
8425 0 => return Air.internedToRef((try mod.intValue(Type.err_int, 0)).toIntern()),
8426 0 => return Air.internedToRef((try mod.intValue(err_int_ty, 0)).toIntern()),
84268427 1 => {
84278428 const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?);
8428 return mod.intRef(Type.err_int, int);
8429 return mod.intRef(err_int_ty, int);
84298430 },
84308431 else => {},
84318432 }
......@@ -8433,7 +8434,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
84338434 }
84348435
84358436 try sema.requireRuntimeBlock(block, src, operand_src);
8436 return block.addBitCast(Type.err_int, operand);
8437 return block.addBitCast(err_int_ty, operand);
84378438}
84388439
84398440fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
......@@ -8445,7 +8446,8 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
84458446 const src = LazySrcLoc.nodeOffset(extra.node);
84468447 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
84478448 const uncasted_operand = try sema.resolveInst(extra.operand);
8448 const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);
8449 const err_int_ty = try mod.errorIntType();
8450 const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src);
84498451
84508452 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
84518453 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod));
......@@ -8459,7 +8461,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
84598461 try sema.requireRuntimeBlock(block, src, operand_src);
84608462 if (block.wantSafety()) {
84618463 const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand);
8462 const zero_val = Air.internedToRef((try mod.intValue(Type.err_int, 0)).toIntern());
8464 const zero_val = Air.internedToRef((try mod.intValue(err_int_ty, 0)).toIntern());
84638465 const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);
84648466 const ok = try block.addBinOp(.bool_and, is_lt_len, is_non_zero);
84658467 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
......@@ -21919,10 +21921,11 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2191921921 }
2192021922
2192121923 try sema.requireRuntimeBlock(block, src, operand_src);
21924 const err_int_ty = try mod.errorIntType();
2192221925 if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) {
2192321926 if (dest_tag == .ErrorUnion) {
2192421927 const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);
21925 const err_int = try block.addBitCast(Type.err_int, err_code);
21928 const err_int = try block.addBitCast(err_int_ty, err_code);
2192621929 const zero_u16 = Air.internedToRef(try mod.intern(.{
2192721930 .int = .{ .ty = .u16_type, .storage = .{ .u64 = 0 } },
2192821931 }));
......@@ -21938,7 +21941,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2193821941 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
2193921942 }
2194021943 } else {
21941 const err_int_inst = try block.addBitCast(Type.err_int, operand);
21944 const err_int_inst = try block.addBitCast(err_int_ty, operand);
2194221945 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
2194321946 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
2194421947 }
src/arch/wasm/CodeGen.zig+7-4
......@@ -3302,6 +3302,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
33023302 return WValue{ .imm32 = int };
33033303 },
33043304 .error_union => |error_union| {
3305 const err_int_ty = try mod.errorIntType();
33053306 const err_tv: TypedValue = switch (error_union.val) {
33063307 .err_name => |err_name| .{
33073308 .ty = ty.errorUnionSet(mod),
......@@ -3311,8 +3312,8 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
33113312 } })).toValue(),
33123313 },
33133314 .payload => .{
3314 .ty = Type.err_int,
3315 .val = try mod.intValue(Type.err_int, 0),
3315 .ty = err_int_ty,
3316 .val = try mod.intValue(err_int_ty, 0),
33163317 },
33173318 };
33183319 const payload_type = ty.errorUnionPayload(mod);
......@@ -3711,8 +3712,10 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37113712 const errors_len = WValue{ .memory = sym_index };
37123713
37133714 try func.emitWValue(operand);
3714 const errors_len_val = try func.load(errors_len, Type.err_int, 0);
3715 const result = try func.cmp(.stack, errors_len_val, Type.err_int, .lt);
3715 const mod = func.bin_file.base.options.module.?;
3716 const err_int_ty = try mod.errorIntType();
3717 const errors_len_val = try func.load(errors_len, err_int_ty, 0);
3718 const result = try func.cmp(.stack, errors_len_val, err_int_ty, .lt);
37163719
37173720 return func.finishAir(inst, try result.toLocal(func, Type.bool), &.{un_op});
37183721}
src/codegen.zig+3-2
......@@ -1054,6 +1054,7 @@ pub fn genTypedValue(
10541054 const payload_type = typed_value.ty.errorUnionPayload(mod);
10551055 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
10561056 // We use the error type directly as the type.
1057 const err_int_ty = try mod.errorIntType();
10571058 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {
10581059 .err_name => |err_name| return genTypedValue(bin_file, src_loc, .{
10591060 .ty = err_type,
......@@ -1063,8 +1064,8 @@ pub fn genTypedValue(
10631064 } })).toValue(),
10641065 }, owner_decl_index),
10651066 .payload => return genTypedValue(bin_file, src_loc, .{
1066 .ty = Type.err_int,
1067 .val = try mod.intValue(Type.err_int, 0),
1067 .ty = err_int_ty,
1068 .val = try mod.intValue(err_int_ty, 0),
10681069 }, owner_decl_index),
10691070 }
10701071 }
src/codegen/c.zig+20-13
......@@ -1038,6 +1038,7 @@ pub const DeclGen = struct {
10381038 .error_union => |error_union| {
10391039 const payload_ty = ty.errorUnionPayload(mod);
10401040 const error_ty = ty.errorUnionSet(mod);
1041 const err_int_ty = try mod.errorIntType();
10411042 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
10421043 switch (error_union.val) {
10431044 .err_name => |err_name| return dg.renderValue(
......@@ -1051,8 +1052,8 @@ pub const DeclGen = struct {
10511052 ),
10521053 .payload => return dg.renderValue(
10531054 writer,
1054 Type.err_int,
1055 try mod.intValue(Type.err_int, 0),
1055 err_int_ty,
1056 try mod.intValue(err_int_ty, 0),
10561057 location,
10571058 ),
10581059 }
......@@ -1087,8 +1088,8 @@ pub const DeclGen = struct {
10871088 ),
10881089 .payload => try dg.renderValue(
10891090 writer,
1090 Type.err_int,
1091 try mod.intValue(Type.err_int, 0),
1091 err_int_ty,
1092 try mod.intValue(err_int_ty, 0),
10921093 location,
10931094 ),
10941095 }
......@@ -1244,7 +1245,7 @@ pub const DeclGen = struct {
12441245 payload_ty,
12451246 switch (opt.val) {
12461247 .none => switch (payload_ty.zigTypeTag(mod)) {
1247 .ErrorSet => try mod.intValue(Type.err_int, 0),
1248 .ErrorSet => try mod.intValue(try mod.errorIntType(), 0),
12481249 .Pointer => try mod.getCoerced(val, payload_ty),
12491250 else => unreachable,
12501251 },
......@@ -5196,6 +5197,7 @@ fn airIsNull(
51965197 const operand_ty = f.typeOf(un_op);
51975198 const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
51985199 const payload_ty = optional_ty.optionalChild(mod);
5200 const err_int_ty = try mod.errorIntType();
51995201
52005202 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
52015203 TypedValue{ .ty = Type.bool, .val = Value.true }
......@@ -5203,7 +5205,7 @@ fn airIsNull(
52035205 // operand is a regular pointer, test `operand !=/== NULL`
52045206 TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) }
52055207 else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
5206 TypedValue{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, 0) }
5208 TypedValue{ .ty = err_int_ty, .val = try mod.intValue(err_int_ty, 0) }
52075209 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
52085210 try writer.writeAll(".ptr");
52095211 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
......@@ -5689,8 +5691,10 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
56895691 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
56905692 else
56915693 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
5692 else
5693 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Initializer);
5694 else {
5695 const err_int_ty = try mod.errorIntType();
5696 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Initializer);
5697 }
56945698 }
56955699 try writer.writeAll(";\n");
56965700 return local;
......@@ -5811,12 +5815,13 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
58115815 const error_union_ty = f.typeOf(ty_op.operand).childType(mod);
58125816
58135817 const payload_ty = error_union_ty.errorUnionPayload(mod);
5818 const err_int_ty = try mod.errorIntType();
58145819
58155820 // First, set the non-error value.
58165821 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
58175822 try f.writeCValueDeref(writer, operand);
58185823 try writer.writeAll(" = ");
5819 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
5824 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
58205825 try writer.writeAll(";\n ");
58215826
58225827 return operand;
......@@ -5824,7 +5829,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
58245829 try reap(f, inst, &.{ty_op.operand});
58255830 try f.writeCValueDeref(writer, operand);
58265831 try writer.writeAll(".error = ");
5827 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
5832 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
58285833 try writer.writeAll(";\n");
58295834
58305835 // Then return the payload pointer (only if it is used)
......@@ -5880,7 +5885,8 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
58805885 else
58815886 try f.writeCValueMember(writer, local, .{ .identifier = "error" });
58825887 try a.assign(f, writer);
5883 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
5888 const err_int_ty = try mod.errorIntType();
5889 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
58845890 try a.end(f, writer);
58855891 }
58865892 return local;
......@@ -5902,6 +5908,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
59025908 try f.writeCValue(writer, local, .Other);
59035909 try writer.writeAll(" = ");
59045910
5911 const err_int_ty = try mod.errorIntType();
59055912 if (!error_ty.errorSetIsEmpty(mod))
59065913 if (payload_ty.hasRuntimeBits(mod))
59075914 if (is_ptr)
......@@ -5911,11 +5918,11 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
59115918 else
59125919 try f.writeCValue(writer, operand, .Other)
59135920 else
5914 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
5921 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
59155922 try writer.writeByte(' ');
59165923 try writer.writeAll(operator);
59175924 try writer.writeByte(' ');
5918 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
5925 try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
59195926 try writer.writeAll(";\n");
59205927 return local;
59215928}
src/codegen/llvm.zig+59-44
......@@ -1111,7 +1111,7 @@ pub const Object = struct {
11111111 // }
11121112
11131113 const lhs = wip.arg(0);
1114 const rhs = try o.builder.intValue(Builder.Type.err_int, errors_len);
1114 const rhs = try o.builder.intValue(try o.errorIntType(), errors_len);
11151115 const is_lt = try wip.icmp(.ult, lhs, rhs, "");
11161116 _ = try wip.ret(is_lt);
11171117 try wip.finish();
......@@ -3121,6 +3121,10 @@ pub const Object = struct {
31213121 return variable_index;
31223122 }
31233123
3124 fn errorIntType(o: *Object) Allocator.Error!Builder.Type {
3125 return o.builder.intType(o.module.errorSetBits());
3126 }
3127
31243128 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
31253129 const ty = try o.lowerTypeInner(t);
31263130 const mod = o.module;
......@@ -3192,7 +3196,7 @@ pub const Object = struct {
31923196 .bool_type => .i1,
31933197 .void_type => .void,
31943198 .type_type => unreachable,
3195 .anyerror_type => Builder.Type.err_int,
3199 .anyerror_type => try o.errorIntType(),
31963200 .comptime_int_type,
31973201 .comptime_float_type,
31983202 .noreturn_type,
......@@ -3213,7 +3217,7 @@ pub const Object = struct {
32133217 .optional_noreturn_type => unreachable,
32143218 .anyerror_void_error_union_type,
32153219 .adhoc_inferred_error_set_type,
3216 => Builder.Type.err_int,
3220 => try o.errorIntType(),
32173221 .generic_poison_type,
32183222 .empty_struct_type,
32193223 => unreachable,
......@@ -3282,16 +3286,17 @@ pub const Object = struct {
32823286 },
32833287 .anyframe_type => @panic("TODO implement lowerType for AnyFrame types"),
32843288 .error_union_type => |error_union_type| {
3285 const error_type = Builder.Type.err_int;
3289 const error_type = try o.errorIntType();
32863290 if (!error_union_type.payload_type.toType().hasRuntimeBitsIgnoreComptime(mod))
32873291 return error_type;
32883292 const payload_type = try o.lowerType(error_union_type.payload_type.toType());
3293 const err_int_ty = try mod.errorIntType();
32893294
32903295 const payload_align = error_union_type.payload_type.toType().abiAlignment(mod);
3291 const error_align = Type.err_int.abiAlignment(mod);
3296 const error_align = err_int_ty.abiAlignment(mod);
32923297
32933298 const payload_size = error_union_type.payload_type.toType().abiSize(mod);
3294 const error_size = Type.err_int.abiSize(mod);
3299 const error_size = err_int_ty.abiSize(mod);
32953300
32963301 var fields: [3]Builder.Type = undefined;
32973302 var fields_len: usize = 2;
......@@ -3552,7 +3557,7 @@ pub const Object = struct {
35523557 },
35533558 .enum_type => |enum_type| try o.lowerType(enum_type.tag_ty.toType()),
35543559 .func_type => |func_type| try o.lowerTypeFn(func_type),
3555 .error_set_type, .inferred_error_set_type => Builder.Type.err_int,
3560 .error_set_type, .inferred_error_set_type => try o.errorIntType(),
35563561 // values, not types
35573562 .undef,
35583563 .runtime_value,
......@@ -3735,7 +3740,7 @@ pub const Object = struct {
37353740 },
37363741 .err => |err| {
37373742 const int = try mod.getErrorValue(err.name);
3738 const llvm_int = try o.builder.intConst(Builder.Type.err_int, int);
3743 const llvm_int = try o.builder.intConst(try o.errorIntType(), int);
37393744 return llvm_int;
37403745 },
37413746 .error_union => |error_union| {
......@@ -3744,8 +3749,9 @@ pub const Object = struct {
37443749 .ty = ty.errorUnionSet(mod).toIntern(),
37453750 .name = err_name,
37463751 } }),
3747 .payload => (try mod.intValue(Type.err_int, 0)).toIntern(),
3752 .payload => (try mod.intValue(try mod.errorIntType(), 0)).toIntern(),
37483753 };
3754 const err_int_ty = try mod.errorIntType();
37493755 const payload_type = ty.errorUnionPayload(mod);
37503756 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
37513757 // We use the error type directly as the type.
......@@ -3753,7 +3759,7 @@ pub const Object = struct {
37533759 }
37543760
37553761 const payload_align = payload_type.abiAlignment(mod);
3756 const error_align = Type.err_int.abiAlignment(mod);
3762 const error_align = err_int_ty.abiAlignment(mod);
37573763 const llvm_error_value = try o.lowerValue(err_val);
37583764 const llvm_payload_value = try o.lowerValue(switch (error_union.val) {
37593765 .err_name => try mod.intern(.{ .undef = payload_type.toIntern() }),
......@@ -4288,8 +4294,9 @@ pub const Object = struct {
42884294 return parent_ptr;
42894295 }
42904296
4297 const err_int_ty = try mod.errorIntType();
42914298 const payload_align = payload_ty.abiAlignment(mod);
4292 const err_align = Type.err_int.abiAlignment(mod);
4299 const err_align = err_int_ty.abiAlignment(mod);
42934300 const index: u32 = if (payload_align.compare(.gt, err_align)) 2 else 1;
42944301 return o.builder.gepConst(.inbounds, try o.lowerType(eu_ty), parent_ptr, null, &.{
42954302 try o.builder.intConst(.i32, 0), try o.builder.intConst(.i32, index),
......@@ -5404,7 +5411,7 @@ pub const FuncGen = struct {
54045411 // Functions with an empty error set are emitted with an error code
54055412 // return type and return zero so they can be function pointers coerced
54065413 // to functions that return anyerror.
5407 _ = try self.wip.ret(try o.builder.intValue(Builder.Type.err_int, 0));
5414 _ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(), 0));
54085415 } else {
54095416 _ = try self.wip.retVoid();
54105417 }
......@@ -5446,7 +5453,7 @@ pub const FuncGen = struct {
54465453 // Functions with an empty error set are emitted with an error code
54475454 // return type and return zero so they can be function pointers coerced
54485455 // to functions that return anyerror.
5449 _ = try self.wip.ret(try o.builder.intValue(Builder.Type.err_int, 0));
5456 _ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(), 0));
54505457 } else {
54515458 _ = try self.wip.retVoid();
54525459 }
......@@ -5793,24 +5800,25 @@ pub const FuncGen = struct {
57935800 const payload_ty = err_union_ty.errorUnionPayload(mod);
57945801 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
57955802 const err_union_llvm_ty = try o.lowerType(err_union_ty);
5803 const error_type = try o.errorIntType();
57965804
57975805 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
57985806 const loaded = loaded: {
57995807 if (!payload_has_bits) {
58005808 // TODO add alignment to this load
58015809 break :loaded if (operand_is_ptr)
5802 try fg.wip.load(.normal, Builder.Type.err_int, err_union, .default, "")
5810 try fg.wip.load(.normal, error_type, err_union, .default, "")
58035811 else
58045812 err_union;
58055813 }
5806 const err_field_index = errUnionErrorOffset(payload_ty, mod);
5814 const err_field_index = try errUnionErrorOffset(payload_ty, mod);
58075815 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
58085816 const err_field_ptr =
58095817 try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, "");
58105818 // TODO add alignment to this load
58115819 break :loaded try fg.wip.load(
58125820 .normal,
5813 Builder.Type.err_int,
5821 error_type,
58145822 err_field_ptr,
58155823 .default,
58165824 "",
......@@ -5818,7 +5826,7 @@ pub const FuncGen = struct {
58185826 }
58195827 break :loaded try fg.wip.extractValue(err_union, &.{err_field_index}, "");
58205828 };
5821 const zero = try o.builder.intValue(Builder.Type.err_int, 0);
5829 const zero = try o.builder.intValue(error_type, 0);
58225830 const is_err = try fg.wip.icmp(.ne, loaded, zero, "");
58235831
58245832 const return_block = try fg.wip.block(1, "TryRet");
......@@ -5832,7 +5840,7 @@ pub const FuncGen = struct {
58325840 }
58335841 if (is_unused) return .none;
58345842 if (!payload_has_bits) return if (operand_is_ptr) err_union else .none;
5835 const offset = errUnionPayloadOffset(payload_ty, mod);
5843 const offset = try errUnionPayloadOffset(payload_ty, mod);
58365844 if (operand_is_ptr) {
58375845 return fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, "");
58385846 } else if (isByRef(err_union_ty, mod)) {
......@@ -7058,7 +7066,8 @@ pub const FuncGen = struct {
70587066 const operand_ty = self.typeOf(un_op);
70597067 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
70607068 const payload_ty = err_union_ty.errorUnionPayload(mod);
7061 const zero = try o.builder.intValue(Builder.Type.err_int, 0);
7069 const error_type = try o.errorIntType();
7070 const zero = try o.builder.intValue(error_type, 0);
70627071
70637072 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
70647073 const val: Builder.Constant = switch (cond) {
......@@ -7077,13 +7086,13 @@ pub const FuncGen = struct {
70777086 return self.wip.icmp(cond, loaded, zero, "");
70787087 }
70797088
7080 const err_field_index = errUnionErrorOffset(payload_ty, mod);
7089 const err_field_index = try errUnionErrorOffset(payload_ty, mod);
70817090
70827091 const loaded = if (operand_is_ptr or isByRef(err_union_ty, mod)) loaded: {
70837092 const err_union_llvm_ty = try o.lowerType(err_union_ty);
70847093 const err_field_ptr =
70857094 try self.wip.gepStruct(err_union_llvm_ty, operand, err_field_index, "");
7086 break :loaded try self.wip.load(.normal, Builder.Type.err_int, err_field_ptr, .default, "");
7095 break :loaded try self.wip.load(.normal, error_type, err_field_ptr, .default, "");
70877096 } else try self.wip.extractValue(operand, &.{err_field_index}, "");
70887097 return self.wip.icmp(cond, loaded, zero, "");
70897098 }
......@@ -7178,7 +7187,7 @@ pub const FuncGen = struct {
71787187 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
71797188 return if (operand_is_ptr) operand else .none;
71807189 }
7181 const offset = errUnionPayloadOffset(payload_ty, mod);
7190 const offset = try errUnionPayloadOffset(payload_ty, mod);
71827191 const err_union_llvm_ty = try o.lowerType(err_union_ty);
71837192 if (operand_is_ptr) {
71847193 return self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");
......@@ -7205,27 +7214,28 @@ pub const FuncGen = struct {
72057214 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
72067215 const operand = try self.resolveInst(ty_op.operand);
72077216 const operand_ty = self.typeOf(ty_op.operand);
7217 const error_type = try o.errorIntType();
72087218 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
72097219 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
72107220 if (operand_is_ptr) {
72117221 return operand;
72127222 } else {
7213 return o.builder.intValue(Builder.Type.err_int, 0);
7223 return o.builder.intValue(error_type, 0);
72147224 }
72157225 }
72167226
72177227 const payload_ty = err_union_ty.errorUnionPayload(mod);
72187228 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
72197229 if (!operand_is_ptr) return operand;
7220 return self.wip.load(.normal, Builder.Type.err_int, operand, .default, "");
7230 return self.wip.load(.normal, error_type, operand, .default, "");
72217231 }
72227232
7223 const offset = errUnionErrorOffset(payload_ty, mod);
7233 const offset = try errUnionErrorOffset(payload_ty, mod);
72247234
72257235 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
72267236 const err_union_llvm_ty = try o.lowerType(err_union_ty);
72277237 const err_field_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");
7228 return self.wip.load(.normal, Builder.Type.err_int, err_field_ptr, .default, "");
7238 return self.wip.load(.normal, error_type, err_field_ptr, .default, "");
72297239 }
72307240
72317241 return self.wip.extractValue(operand, &.{offset}, "");
......@@ -7239,15 +7249,16 @@ pub const FuncGen = struct {
72397249 const err_union_ty = self.typeOf(ty_op.operand).childType(mod);
72407250
72417251 const payload_ty = err_union_ty.errorUnionPayload(mod);
7242 const non_error_val = try o.builder.intValue(Builder.Type.err_int, 0);
7252 const non_error_val = try o.builder.intValue(try o.errorIntType(), 0);
72437253 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
72447254 _ = try self.wip.store(.normal, non_error_val, operand, .default);
72457255 return operand;
72467256 }
72477257 const err_union_llvm_ty = try o.lowerType(err_union_ty);
72487258 {
7249 const error_alignment = Type.err_int.abiAlignment(mod).toLlvm();
7250 const error_offset = errUnionErrorOffset(payload_ty, mod);
7259 const err_int_ty = try mod.errorIntType();
7260 const error_alignment = err_int_ty.abiAlignment(mod).toLlvm();
7261 const error_offset = try errUnionErrorOffset(payload_ty, mod);
72517262 // First set the non-error value.
72527263 const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, "");
72537264 _ = try self.wip.store(.normal, non_error_val, non_null_ptr, error_alignment);
......@@ -7255,7 +7266,7 @@ pub const FuncGen = struct {
72557266 // Then return the payload pointer (only if it is used).
72567267 if (self.liveness.isUnused(inst)) return .none;
72577268
7258 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
7269 const payload_offset = try errUnionPayloadOffset(payload_ty, mod);
72597270 return self.wip.gepStruct(err_union_llvm_ty, operand, payload_offset, "");
72607271 }
72617272
......@@ -7358,11 +7369,11 @@ pub const FuncGen = struct {
73587369 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
73597370 return operand;
73607371 }
7361 const ok_err_code = try o.builder.intValue(Builder.Type.err_int, 0);
7372 const ok_err_code = try o.builder.intValue(try o.errorIntType(), 0);
73627373 const err_un_llvm_ty = try o.lowerType(err_un_ty);
73637374
7364 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
7365 const error_offset = errUnionErrorOffset(payload_ty, mod);
7375 const payload_offset = try errUnionPayloadOffset(payload_ty, mod);
7376 const error_offset = try errUnionErrorOffset(payload_ty, mod);
73667377 if (isByRef(err_un_ty, mod)) {
73677378 const directReturn = self.isNextRet(body_tail);
73687379 const result_ptr = if (directReturn)
......@@ -7374,7 +7385,8 @@ pub const FuncGen = struct {
73747385 };
73757386
73767387 const err_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, error_offset, "");
7377 const error_alignment = Type.err_int.abiAlignment(mod).toLlvm();
7388 const err_int_ty = try mod.errorIntType();
7389 const error_alignment = err_int_ty.abiAlignment(mod).toLlvm();
73787390 _ = try self.wip.store(.normal, ok_err_code, err_ptr, error_alignment);
73797391 const payload_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, payload_offset, "");
73807392 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
......@@ -7398,8 +7410,8 @@ pub const FuncGen = struct {
73987410 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return operand;
73997411 const err_un_llvm_ty = try o.lowerType(err_un_ty);
74007412
7401 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
7402 const error_offset = errUnionErrorOffset(payload_ty, mod);
7413 const payload_offset = try errUnionPayloadOffset(payload_ty, mod);
7414 const error_offset = try errUnionErrorOffset(payload_ty, mod);
74037415 if (isByRef(err_un_ty, mod)) {
74047416 const directReturn = self.isNextRet(body_tail);
74057417 const result_ptr = if (directReturn)
......@@ -7411,7 +7423,8 @@ pub const FuncGen = struct {
74117423 };
74127424
74137425 const err_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, error_offset, "");
7414 const error_alignment = Type.err_int.abiAlignment(mod).toLlvm();
7426 const err_int_ty = try mod.errorIntType();
7427 const error_alignment = err_int_ty.abiAlignment(mod).toLlvm();
74157428 _ = try self.wip.store(.normal, operand, err_ptr, error_alignment);
74167429 const payload_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, payload_offset, "");
74177430 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
......@@ -9368,7 +9381,7 @@ pub const FuncGen = struct {
93689381
93699382 for (names) |name| {
93709383 const err_int = mod.global_error_set.getIndex(name).?;
9371 const this_tag_int_value = try o.builder.intConst(Builder.Type.err_int, err_int);
9384 const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int);
93729385 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
93739386 }
93749387 self.wip.cursor = .{ .block = valid_block };
......@@ -9550,7 +9563,7 @@ pub const FuncGen = struct {
95509563 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
95519564
95529565 const function_index = try o.builder.addFunction(
9553 try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal),
9566 try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal),
95549567 name,
95559568 toLlvmAddressSpace(.generic, o.module.getTarget()),
95569569 );
......@@ -10885,7 +10898,7 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
1088510898 // If the return type is an error set or an error union, then we make this
1088610899 // anyerror return type instead, so that it can be coerced into a function
1088710900 // pointer type which has anyerror as the return type.
10888 return if (return_type.isError(mod)) Builder.Type.err_int else .void;
10901 return if (return_type.isError(mod)) try o.errorIntType() else .void;
1088910902 }
1089010903 const target = mod.getTarget();
1089110904 switch (fn_info.cc) {
......@@ -11638,12 +11651,14 @@ fn buildAllocaInner(
1163811651 return wip.conv(.unneeded, alloca, .ptr, "");
1163911652}
1164011653
11641fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 {
11642 return @intFromBool(Type.err_int.abiAlignment(mod).compare(.gt, payload_ty.abiAlignment(mod)));
11654fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) !u1 {
11655 const err_int_ty = try mod.errorIntType();
11656 return @intFromBool(err_int_ty.abiAlignment(mod).compare(.gt, payload_ty.abiAlignment(mod)));
1164311657}
1164411658
11645fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u1 {
11646 return @intFromBool(Type.err_int.abiAlignment(mod).compare(.lte, payload_ty.abiAlignment(mod)));
11659fn errUnionErrorOffset(payload_ty: Type, mod: *Module) !u1 {
11660 const err_int_ty = try mod.errorIntType();
11661 return @intFromBool(err_int_ty.abiAlignment(mod).compare(.lte, payload_ty.abiAlignment(mod)));
1164711662}
1164811663
1164911664/// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location
src/codegen/llvm/Builder.zig-1
......@@ -159,7 +159,6 @@ pub const Type = enum(u32) {
159159 none = std.math.maxInt(u32),
160160 _,
161161
162 pub const err_int = Type.i16;
163162 pub const ptr_amdgpu_constant =
164163 @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));
165164
src/codegen/spirv.zig+3-2
......@@ -742,16 +742,17 @@ const DeclGen = struct {
742742 .error_union => |error_union| {
743743 // TODO: Error unions may be constructed with constant instructions if the payload type
744744 // allows it. For now, just generate it here regardless.
745 const err_int_ty = try mod.errorIntType();
745746 const err_ty = switch (error_union.val) {
746747 .err_name => ty.errorUnionSet(mod),
747 .payload => Type.err_int,
748 .payload => err_int_ty,
748749 };
749750 const err_val = switch (error_union.val) {
750751 .err_name => |err_name| (try mod.intern(.{ .err = .{
751752 .ty = ty.errorUnionSet(mod).toIntern(),
752753 .name = err_name,
753754 } })).toValue(),
754 .payload => try mod.intValue(Type.err_int, 0),
755 .payload => try mod.intValue(err_int_ty, 0),
755756 };
756757 const payload_ty = ty.errorUnionPayload(mod);
757758 const eu_layout = self.errorUnionLayout(payload_ty);
src/main.zig+9
......@@ -421,6 +421,7 @@ const usage_build_generic =
421421 \\ --deps [dep],[dep],... Set dependency names for the root package
422422 \\ dep: [[import=]name]
423423 \\ --main-mod-path Set the directory of the root module
424 \\ --error-limit [num] Set the maximum amount of distinct error values
424425 \\ -fPIC Force-enable Position Independent Code
425426 \\ -fno-PIC Force-disable Position Independent Code
426427 \\ -fPIE Force-enable Position Independent Executable
......@@ -911,6 +912,8 @@ fn buildOutputType(
911912 var error_tracing: ?bool = null;
912913 var pdb_out_path: ?[]const u8 = null;
913914 var dwarf_format: ?std.dwarf.Format = null;
915 var error_limit: ?Module.ErrorInt = null;
916
914917 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
915918 // This array is populated by zig cc frontend and then has to be converted to zig-style
916919 // CPU features.
......@@ -1040,6 +1043,11 @@ fn buildOutputType(
10401043 root_deps_str = args_iter.nextOrFatal();
10411044 } else if (mem.eql(u8, arg, "--main-mod-path")) {
10421045 main_mod_path = args_iter.nextOrFatal();
1046 } else if (mem.eql(u8, arg, "--error-limit")) {
1047 const next_arg = args_iter.nextOrFatal();
1048 error_limit = std.fmt.parseUnsigned(Module.ErrorInt, next_arg, 0) catch |err| {
1049 fatal("unable to parse error limit '{s}': {s}", .{ next_arg, @errorName(err) });
1050 };
10431051 } else if (mem.eql(u8, arg, "-cflags")) {
10441052 extra_cflags.shrinkRetainingCapacity(0);
10451053 while (true) {
......@@ -3546,6 +3554,7 @@ fn buildOutputType(
35463554 .reference_trace = reference_trace,
35473555 .error_tracing = error_tracing,
35483556 .pdb_out_path = pdb_out_path,
3557 .error_limit = error_limit,
35493558 }) catch |err| switch (err) {
35503559 error.LibCUnavailable => {
35513560 const target = target_info.target;
src/type.zig+26-22
......@@ -905,8 +905,11 @@ pub const Type = struct {
905905 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
906906 .error_union_type => |info| return abiAlignmentAdvancedErrorUnion(ty, mod, strat, info.payload_type.toType()),
907907
908 // TODO revisit this when we have the concept of the error tag type
909 .error_set_type, .inferred_error_set_type => return .{ .scalar = .@"2" },
908 .error_set_type, .inferred_error_set_type => {
909 const bits = mod.errorSetBits();
910 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
911 return .{ .scalar = intAbiAlignment(bits, target) };
912 },
910913
911914 // represents machine code; not a pointer
912915 .func_type => |func_type| return .{
......@@ -967,10 +970,11 @@ pub const Type = struct {
967970 else => return .{ .scalar = .@"16" },
968971 },
969972
970 // TODO revisit this when we have the concept of the error tag type
971 .anyerror,
972 .adhoc_inferred_error_set,
973 => return .{ .scalar = .@"2" },
973 .anyerror, .adhoc_inferred_error_set => {
974 const bits = mod.errorSetBits();
975 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
976 return .{ .scalar = intAbiAlignment(bits, target) };
977 },
974978
975979 .void,
976980 .type,
......@@ -1284,8 +1288,11 @@ pub const Type = struct {
12841288
12851289 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
12861290
1287 // TODO revisit this when we have the concept of the error tag type
1288 .error_set_type, .inferred_error_set_type => return AbiSizeAdvanced{ .scalar = 2 },
1291 .error_set_type, .inferred_error_set_type => {
1292 const bits = mod.errorSetBits();
1293 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1294 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
1295 },
12891296
12901297 .error_union_type => |error_union_type| {
12911298 const payload_ty = error_union_type.payload_type.toType();
......@@ -1379,10 +1386,11 @@ pub const Type = struct {
13791386 .enum_literal,
13801387 => return AbiSizeAdvanced{ .scalar = 0 },
13811388
1382 // TODO revisit this when we have the concept of the error tag type
1383 .anyerror,
1384 .adhoc_inferred_error_set,
1385 => return AbiSizeAdvanced{ .scalar = 2 },
1389 .anyerror, .adhoc_inferred_error_set => {
1390 const bits = mod.errorSetBits();
1391 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1392 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
1393 },
13861394
13871395 .prefetch_options => unreachable, // missing call to resolveTypeFields
13881396 .export_options => unreachable, // missing call to resolveTypeFields
......@@ -1576,8 +1584,7 @@ pub const Type = struct {
15761584 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
15771585 },
15781586
1579 // TODO revisit this when we have the concept of the error tag type
1580 .error_set_type, .inferred_error_set_type => return 16,
1587 .error_set_type, .inferred_error_set_type => return mod.errorSetBits(),
15811588
15821589 .error_union_type => {
15831590 // Optionals and error unions are not packed so their bitsize
......@@ -1610,10 +1617,9 @@ pub const Type = struct {
16101617 .bool => return 1,
16111618 .void => return 0,
16121619
1613 // TODO revisit this when we have the concept of the error tag type
16141620 .anyerror,
16151621 .adhoc_inferred_error_set,
1616 => return 16,
1622 => return mod.errorSetBits(),
16171623
16181624 .anyopaque => unreachable,
16191625 .type => unreachable,
......@@ -2172,8 +2178,7 @@ pub const Type = struct {
21722178
21732179 while (true) switch (ty.toIntern()) {
21742180 .anyerror_type, .adhoc_inferred_error_set_type => {
2175 // TODO revisit this when error sets support custom int types
2176 return .{ .signedness = .unsigned, .bits = 16 };
2181 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
21772182 },
21782183 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
21792184 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
......@@ -2192,8 +2197,9 @@ pub const Type = struct {
21922197 .enum_type => |enum_type| ty = enum_type.tag_ty.toType(),
21932198 .vector_type => |vector_type| ty = vector_type.child.toType(),
21942199
2195 // TODO revisit this when error sets support custom int types
2196 .error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = 16 },
2200 .error_set_type, .inferred_error_set_type => {
2201 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
2202 },
21972203
21982204 .anon_struct_type => unreachable,
21992205
......@@ -3303,8 +3309,6 @@ pub const Type = struct {
33033309
33043310 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
33053311
3306 pub const err_int = Type.u16;
3307
33083312 pub fn smallestUnsignedBits(max: u64) u16 {
33093313 if (max == 0) return 0;
33103314 const base = std.math.log2(max);
src/value.zig+15-8
......@@ -701,15 +701,20 @@ pub const Value = struct {
701701 }
702702 },
703703 .ErrorSet => {
704 // TODO revisit this when we have the concept of the error tag type
705 const Int = u16;
704 const bits = mod.errorSetBits();
705 const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
706
706707 const name = switch (ip.indexToKey(val.toIntern())) {
707708 .err => |err| err.name,
708709 .error_union => |error_union| error_union.val.err_name,
709710 else => unreachable,
710711 };
711 const int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(name).?));
712 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @as(Int, @intCast(int)), endian);
712 var bigint_buffer: BigIntSpace = undefined;
713 const bigint = BigIntMutable.init(
714 &bigint_buffer.limbs,
715 mod.global_error_set.getIndex(name).?,
716 ).toConst();
717 bigint.writeTwosComplement(buffer[0..byte_count], endian);
713718 },
714719 .Union => switch (ty.containerLayout(mod)) {
715720 .Auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already
......@@ -987,10 +992,12 @@ pub const Value = struct {
987992 }
988993 },
989994 .ErrorSet => {
990 // TODO revisit this when we have the concept of the error tag type
991 const Int = u16;
992 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);
993 const name = mod.global_error_set.keys()[@as(usize, @intCast(int))];
995 const bits = mod.errorSetBits();
996 const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
997 const int = std.mem.readVarInt(u64, buffer[0..byte_count], endian);
998 const index = (int << @as(u6, @intCast(64 - bits))) >> @as(u6, @intCast(64 - bits));
999 const name = mod.global_error_set.keys()[@intCast(index)];
1000
9941001 return (try mod.intern(.{ .err = .{
9951002 .ty = ty.toIntern(),
9961003 .name = name,