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" {...@@ -5373,8 +5373,9 @@ test "fn reflection" {
5373 gets assigned the same integer value.5373 gets assigned the same integer value.
5374 </p>5374 </p>
5375 <p>5375 <p>
5376 The number of unique error values across the entire compilation should determine the size of the error set type.5376 The error set type defaults to a {#syntax#}u16{#endsyntax#}, though if the maximum number of distinct
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>.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.
5378 </p>5379 </p>
5379 <p>5380 <p>
5380 You can {#link|coerce|Type Coercion#} an error from a subset to a superset:5381 You can {#link|coerce|Type Coercion#} an error from a subset to a superset:
...@@ -8373,7 +8374,7 @@ test "main" {...@@ -8373,7 +8374,7 @@ test "main" {
8373 {#header_close#}8374 {#header_close#}
83748375
8375 {#header_open|@errorFromInt#}8376 {#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>
8377 <p>8378 <p>
8378 Converts from the integer representation of an error into {#link|The Global Error Set#} type.8379 Converts from the integer representation of an error into {#link|The Global Error Set#} type.
8379 </p>8380 </p>
...@@ -8694,7 +8695,7 @@ test "integer cast panic" {...@@ -8694,7 +8695,7 @@ test "integer cast panic" {
8694 {#header_close#}8695 {#header_close#}
86958696
8696 {#header_open|@intFromError#}8697 {#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>
8698 <p>8699 <p>
8699 Supports the following types:8700 Supports the following types:
8700 </p>8701 </p>
src/AstGen.zig+1-1
...@@ -8432,7 +8432,7 @@ fn builtinCall(...@@ -8432,7 +8432,7 @@ fn builtinCall(
8432 return rvalue(gz, ri, result, node);8432 return rvalue(gz, ri, result, node);
8433 },8433 },
8434 .error_from_int => {8434 .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]);
8436 const result = try gz.addExtendedPayload(.error_from_int, Zir.Inst.UnNode{8436 const result = try gz.addExtendedPayload(.error_from_int, Zir.Inst.UnNode{
8437 .node = gz.nodeIndexToRelative(node),8437 .node = gz.nodeIndexToRelative(node),
8438 .operand = operand,8438 .operand = operand,
src/Compilation.zig+23
...@@ -739,6 +739,7 @@ pub const InitOptions = struct {...@@ -739,6 +739,7 @@ pub const InitOptions = struct {
739 pdb_source_path: ?[]const u8 = null,739 pdb_source_path: ?[]const u8 = null,
740 /// (Windows) PDB output path740 /// (Windows) PDB output path
741 pdb_out_path: ?[]const u8 = null,741 pdb_out_path: ?[]const u8 = null,
742 error_limit: ?Module.ErrorInt = null,
742};743};
743744
744fn addModuleTableToCacheHash(745fn addModuleTableToCacheHash(
...@@ -1432,6 +1433,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1432,6 +1433,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1432 .local_zir_cache = local_zir_cache,1433 .local_zir_cache = local_zir_cache,
1433 .emit_h = emit_h,1434 .emit_h = emit_h,
1434 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),1435 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
1436 .error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1),
1435 };1437 };
1436 try module.init();1438 try module.init();
14371439
...@@ -2486,6 +2488,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2486,6 +2488,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2486 man.hash.add(comp.bin_file.options.skip_linker_dependencies);2488 man.hash.add(comp.bin_file.options.skip_linker_dependencies);
2487 man.hash.add(comp.bin_file.options.parent_compilation_link_libc);2489 man.hash.add(comp.bin_file.options.parent_compilation_link_libc);
2488 man.hash.add(mod.emit_h != null);2490 man.hash.add(mod.emit_h != null);
2491 man.hash.add(mod.error_limit);
2489 }2492 }
24902493
2491 try man.addOptionalFile(comp.bin_file.options.linker_script);2494 try man.addOptionalFile(comp.bin_file.options.linker_script);
...@@ -2866,6 +2869,10 @@ pub fn totalErrorCount(self: *Compilation) u32 {...@@ -2866,6 +2869,10 @@ pub fn totalErrorCount(self: *Compilation) u32 {
2866 }2869 }
2867 }2870 }
2868 }2871 }
2872
2873 if (module.global_error_set.entries.len - 1 > module.error_limit) {
2874 total += 1;
2875 }
2869 }2876 }
28702877
2871 // The "no entry point found" error only counts if there are no semantic analysis errors.2878 // 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 {...@@ -3016,6 +3023,22 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
3016 for (module.failed_exports.values()) |value| {3023 for (module.failed_exports.values()) |value| {
3017 try addModuleErrorMsg(module, &bundle, value.*);3024 try addModuleErrorMsg(module, &bundle, value.*);
3018 }3025 }
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 }
3019 }3042 }
30203043
3021 if (bundle.root_list.items.len == 0) {3044 if (bundle.root_list.items.len == 0) {
src/Module.zig+12
...@@ -137,6 +137,9 @@ deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},...@@ -137,6 +137,9 @@ deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
137/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.137/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
138global_error_set: GlobalErrorSet = .{},138global_error_set: GlobalErrorSet = .{},
139139
140/// Maximum amount of distinct error values, set by --error-limit
141error_limit: ErrorInt,
142
140/// Incrementing integer used to compare against the corresponding Decl143/// Incrementing integer used to compare against the corresponding Decl
141/// field to determine whether a Decl's status applies to an ongoing update, or a144/// field to determine whether a Decl's status applies to an ongoing update, or a
142/// previous analysis.145/// previous analysis.
...@@ -5020,6 +5023,11 @@ pub fn getErrorValueFromSlice(...@@ -5020,6 +5023,11 @@ pub fn getErrorValueFromSlice(
5020 return getErrorValue(mod, interned_name);5023 return getErrorValue(mod, interned_name);
5021}5024}
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
5023pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {5031pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {
5024 const src_decl = mod.declPtr(block.src_decl);5032 const src_decl = mod.declPtr(block.src_decl);
5025 return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value);5033 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...@@ -5898,6 +5906,10 @@ pub fn intType(mod: *Module, signedness: std.builtin.Signedness, bits: u16) Allo
5898 } })).toType();5906 } })).toType();
5899}5907}
59005908
5909pub fn errorIntType(mod: *Module) std.mem.Allocator.Error!Type {
5910 return mod.intType(.unsigned, mod.errorSetBits());
5911}
5912
5901pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type {5913pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type {
5902 const i = try intern(mod, .{ .array_type = info });5914 const i = try intern(mod, .{ .array_type = info });
5903 return i.toType();5915 return i.toType();
src/Sema.zig+12-9
...@@ -8404,14 +8404,15 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8404,14 +8404,15 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8404 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };8404 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
8405 const uncasted_operand = try sema.resolveInst(extra.operand);8405 const uncasted_operand = try sema.resolveInst(extra.operand);
8406 const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src);8406 const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src);
8407 const err_int_ty = try mod.errorIntType();
84078408
8408 if (try sema.resolveMaybeUndefVal(operand)) |val| {8409 if (try sema.resolveMaybeUndefVal(operand)) |val| {
8409 if (val.isUndef(mod)) {8410 if (val.isUndef(mod)) {
8410 return mod.undefRef(Type.err_int);8411 return mod.undefRef(err_int_ty);
8411 }8412 }
8412 const err_name = ip.indexToKey(val.toIntern()).err.name;8413 const err_name = ip.indexToKey(val.toIntern()).err.name;
8413 return Air.internedToRef((try mod.intValue(8414 return Air.internedToRef((try mod.intValue(
8414 Type.err_int,8415 err_int_ty,
8415 try mod.getErrorValue(err_name),8416 try mod.getErrorValue(err_name),
8416 )).toIntern());8417 )).toIntern());
8417 }8418 }
...@@ -8422,10 +8423,10 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8422,10 +8423,10 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8422 else => |err_set_ty_index| {8423 else => |err_set_ty_index| {
8423 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;8424 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
8424 switch (names.len) {8425 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()),
8426 1 => {8427 1 => {
8427 const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?);8428 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);
8429 },8430 },
8430 else => {},8431 else => {},
8431 }8432 }
...@@ -8433,7 +8434,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8433,7 +8434,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8433 }8434 }
84348435
8435 try sema.requireRuntimeBlock(block, src, operand_src);8436 try sema.requireRuntimeBlock(block, src, operand_src);
8436 return block.addBitCast(Type.err_int, operand);8437 return block.addBitCast(err_int_ty, operand);
8437}8438}
84388439
8439fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {8440fn 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...@@ -8445,7 +8446,8 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8445 const src = LazySrcLoc.nodeOffset(extra.node);8446 const src = LazySrcLoc.nodeOffset(extra.node);
8446 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };8447 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
8447 const uncasted_operand = try sema.resolveInst(extra.operand);8448 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
8450 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {8452 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
8451 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod));8453 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...@@ -8459,7 +8461,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8459 try sema.requireRuntimeBlock(block, src, operand_src);8461 try sema.requireRuntimeBlock(block, src, operand_src);
8460 if (block.wantSafety()) {8462 if (block.wantSafety()) {
8461 const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand);8463 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());
8463 const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);8465 const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);
8464 const ok = try block.addBinOp(.bool_and, is_lt_len, is_non_zero);8466 const ok = try block.addBinOp(.bool_and, is_lt_len, is_non_zero);
8465 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);8467 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
...@@ -21919,10 +21921,11 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -21919,10 +21921,11 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
21919 }21921 }
2192021922
21921 try sema.requireRuntimeBlock(block, src, operand_src);21923 try sema.requireRuntimeBlock(block, src, operand_src);
21924 const err_int_ty = try mod.errorIntType();
21922 if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) {21925 if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) {
21923 if (dest_tag == .ErrorUnion) {21926 if (dest_tag == .ErrorUnion) {
21924 const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);21927 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);
21926 const zero_u16 = Air.internedToRef(try mod.intern(.{21929 const zero_u16 = Air.internedToRef(try mod.intern(.{
21927 .int = .{ .ty = .u16_type, .storage = .{ .u64 = 0 } },21930 .int = .{ .ty = .u16_type, .storage = .{ .u64 = 0 } },
21928 }));21931 }));
...@@ -21938,7 +21941,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -21938,7 +21941,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
21938 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);21941 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
21939 }21942 }
21940 } else {21943 } 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);
21942 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);21945 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
21943 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);21946 try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
21944 }21947 }
src/arch/wasm/CodeGen.zig+7-4
...@@ -3302,6 +3302,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -3302,6 +3302,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
3302 return WValue{ .imm32 = int };3302 return WValue{ .imm32 = int };
3303 },3303 },
3304 .error_union => |error_union| {3304 .error_union => |error_union| {
3305 const err_int_ty = try mod.errorIntType();
3305 const err_tv: TypedValue = switch (error_union.val) {3306 const err_tv: TypedValue = switch (error_union.val) {
3306 .err_name => |err_name| .{3307 .err_name => |err_name| .{
3307 .ty = ty.errorUnionSet(mod),3308 .ty = ty.errorUnionSet(mod),
...@@ -3311,8 +3312,8 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {...@@ -3311,8 +3312,8 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
3311 } })).toValue(),3312 } })).toValue(),
3312 },3313 },
3313 .payload => .{3314 .payload => .{
3314 .ty = Type.err_int,3315 .ty = err_int_ty,
3315 .val = try mod.intValue(Type.err_int, 0),3316 .val = try mod.intValue(err_int_ty, 0),
3316 },3317 },
3317 };3318 };
3318 const payload_type = ty.errorUnionPayload(mod);3319 const payload_type = ty.errorUnionPayload(mod);
...@@ -3711,8 +3712,10 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3711,8 +3712,10 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3711 const errors_len = WValue{ .memory = sym_index };3712 const errors_len = WValue{ .memory = sym_index };
37123713
3713 try func.emitWValue(operand);3714 try func.emitWValue(operand);
3714 const errors_len_val = try func.load(errors_len, Type.err_int, 0);3715 const mod = func.bin_file.base.options.module.?;
3715 const result = try func.cmp(.stack, errors_len_val, Type.err_int, .lt);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
3717 return func.finishAir(inst, try result.toLocal(func, Type.bool), &.{un_op});3720 return func.finishAir(inst, try result.toLocal(func, Type.bool), &.{un_op});
3718}3721}
src/codegen.zig+3-2
...@@ -1054,6 +1054,7 @@ pub fn genTypedValue(...@@ -1054,6 +1054,7 @@ pub fn genTypedValue(
1054 const payload_type = typed_value.ty.errorUnionPayload(mod);1054 const payload_type = typed_value.ty.errorUnionPayload(mod);
1055 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {1055 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
1056 // We use the error type directly as the type.1056 // We use the error type directly as the type.
1057 const err_int_ty = try mod.errorIntType();
1057 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {1058 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {
1058 .err_name => |err_name| return genTypedValue(bin_file, src_loc, .{1059 .err_name => |err_name| return genTypedValue(bin_file, src_loc, .{
1059 .ty = err_type,1060 .ty = err_type,
...@@ -1063,8 +1064,8 @@ pub fn genTypedValue(...@@ -1063,8 +1064,8 @@ pub fn genTypedValue(
1063 } })).toValue(),1064 } })).toValue(),
1064 }, owner_decl_index),1065 }, owner_decl_index),
1065 .payload => return genTypedValue(bin_file, src_loc, .{1066 .payload => return genTypedValue(bin_file, src_loc, .{
1066 .ty = Type.err_int,1067 .ty = err_int_ty,
1067 .val = try mod.intValue(Type.err_int, 0),1068 .val = try mod.intValue(err_int_ty, 0),
1068 }, owner_decl_index),1069 }, owner_decl_index),
1069 }1070 }
1070 }1071 }
src/codegen/c.zig+20-13
...@@ -1038,6 +1038,7 @@ pub const DeclGen = struct {...@@ -1038,6 +1038,7 @@ pub const DeclGen = struct {
1038 .error_union => |error_union| {1038 .error_union => |error_union| {
1039 const payload_ty = ty.errorUnionPayload(mod);1039 const payload_ty = ty.errorUnionPayload(mod);
1040 const error_ty = ty.errorUnionSet(mod);1040 const error_ty = ty.errorUnionSet(mod);
1041 const err_int_ty = try mod.errorIntType();
1041 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {1042 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1042 switch (error_union.val) {1043 switch (error_union.val) {
1043 .err_name => |err_name| return dg.renderValue(1044 .err_name => |err_name| return dg.renderValue(
...@@ -1051,8 +1052,8 @@ pub const DeclGen = struct {...@@ -1051,8 +1052,8 @@ pub const DeclGen = struct {
1051 ),1052 ),
1052 .payload => return dg.renderValue(1053 .payload => return dg.renderValue(
1053 writer,1054 writer,
1054 Type.err_int,1055 err_int_ty,
1055 try mod.intValue(Type.err_int, 0),1056 try mod.intValue(err_int_ty, 0),
1056 location,1057 location,
1057 ),1058 ),
1058 }1059 }
...@@ -1087,8 +1088,8 @@ pub const DeclGen = struct {...@@ -1087,8 +1088,8 @@ pub const DeclGen = struct {
1087 ),1088 ),
1088 .payload => try dg.renderValue(1089 .payload => try dg.renderValue(
1089 writer,1090 writer,
1090 Type.err_int,1091 err_int_ty,
1091 try mod.intValue(Type.err_int, 0),1092 try mod.intValue(err_int_ty, 0),
1092 location,1093 location,
1093 ),1094 ),
1094 }1095 }
...@@ -1244,7 +1245,7 @@ pub const DeclGen = struct {...@@ -1244,7 +1245,7 @@ pub const DeclGen = struct {
1244 payload_ty,1245 payload_ty,
1245 switch (opt.val) {1246 switch (opt.val) {
1246 .none => switch (payload_ty.zigTypeTag(mod)) {1247 .none => switch (payload_ty.zigTypeTag(mod)) {
1247 .ErrorSet => try mod.intValue(Type.err_int, 0),1248 .ErrorSet => try mod.intValue(try mod.errorIntType(), 0),
1248 .Pointer => try mod.getCoerced(val, payload_ty),1249 .Pointer => try mod.getCoerced(val, payload_ty),
1249 else => unreachable,1250 else => unreachable,
1250 },1251 },
...@@ -5196,6 +5197,7 @@ fn airIsNull(...@@ -5196,6 +5197,7 @@ fn airIsNull(
5196 const operand_ty = f.typeOf(un_op);5197 const operand_ty = f.typeOf(un_op);
5197 const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;5198 const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
5198 const payload_ty = optional_ty.optionalChild(mod);5199 const payload_ty = optional_ty.optionalChild(mod);
5200 const err_int_ty = try mod.errorIntType();
51995201
5200 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))5202 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
5201 TypedValue{ .ty = Type.bool, .val = Value.true }5203 TypedValue{ .ty = Type.bool, .val = Value.true }
...@@ -5203,7 +5205,7 @@ fn airIsNull(...@@ -5203,7 +5205,7 @@ fn airIsNull(
5203 // operand is a regular pointer, test `operand !=/== NULL`5205 // operand is a regular pointer, test `operand !=/== NULL`
5204 TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) }5206 TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) }
5205 else if (payload_ty.zigTypeTag(mod) == .ErrorSet)5207 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) }
5207 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {5209 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
5208 try writer.writeAll(".ptr");5210 try writer.writeAll(".ptr");
5209 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);5211 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
...@@ -5689,8 +5691,10 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5689,8 +5691,10 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5689 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })5691 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
5690 else5692 else
5691 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })5693 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
5692 else5694 else {
5693 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Initializer);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 }
5694 }5698 }
5695 try writer.writeAll(";\n");5699 try writer.writeAll(";\n");
5696 return local;5700 return local;
...@@ -5811,12 +5815,13 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5811,12 +5815,13 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5811 const error_union_ty = f.typeOf(ty_op.operand).childType(mod);5815 const error_union_ty = f.typeOf(ty_op.operand).childType(mod);
58125816
5813 const payload_ty = error_union_ty.errorUnionPayload(mod);5817 const payload_ty = error_union_ty.errorUnionPayload(mod);
5818 const err_int_ty = try mod.errorIntType();
58145819
5815 // First, set the non-error value.5820 // First, set the non-error value.
5816 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {5821 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5817 try f.writeCValueDeref(writer, operand);5822 try f.writeCValueDeref(writer, operand);
5818 try writer.writeAll(" = ");5823 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);
5820 try writer.writeAll(";\n ");5825 try writer.writeAll(";\n ");
58215826
5822 return operand;5827 return operand;
...@@ -5824,7 +5829,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5824,7 +5829,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5824 try reap(f, inst, &.{ty_op.operand});5829 try reap(f, inst, &.{ty_op.operand});
5825 try f.writeCValueDeref(writer, operand);5830 try f.writeCValueDeref(writer, operand);
5826 try writer.writeAll(".error = ");5831 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);
5828 try writer.writeAll(";\n");5833 try writer.writeAll(";\n");
58295834
5830 // Then return the payload pointer (only if it is used)5835 // Then return the payload pointer (only if it is used)
...@@ -5880,7 +5885,8 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5880,7 +5885,8 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
5880 else5885 else
5881 try f.writeCValueMember(writer, local, .{ .identifier = "error" });5886 try f.writeCValueMember(writer, local, .{ .identifier = "error" });
5882 try a.assign(f, writer);5887 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);
5884 try a.end(f, writer);5890 try a.end(f, writer);
5885 }5891 }
5886 return local;5892 return local;
...@@ -5902,6 +5908,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const...@@ -5902,6 +5908,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
5902 try f.writeCValue(writer, local, .Other);5908 try f.writeCValue(writer, local, .Other);
5903 try writer.writeAll(" = ");5909 try writer.writeAll(" = ");
59045910
5911 const err_int_ty = try mod.errorIntType();
5905 if (!error_ty.errorSetIsEmpty(mod))5912 if (!error_ty.errorSetIsEmpty(mod))
5906 if (payload_ty.hasRuntimeBits(mod))5913 if (payload_ty.hasRuntimeBits(mod))
5907 if (is_ptr)5914 if (is_ptr)
...@@ -5911,11 +5918,11 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const...@@ -5911,11 +5918,11 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
5911 else5918 else
5912 try f.writeCValue(writer, operand, .Other)5919 try f.writeCValue(writer, operand, .Other)
5913 else5920 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);
5915 try writer.writeByte(' ');5922 try writer.writeByte(' ');
5916 try writer.writeAll(operator);5923 try writer.writeAll(operator);
5917 try writer.writeByte(' ');5924 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);
5919 try writer.writeAll(";\n");5926 try writer.writeAll(";\n");
5920 return local;5927 return local;
5921}5928}
src/codegen/llvm.zig+59-44
...@@ -1111,7 +1111,7 @@ pub const Object = struct {...@@ -1111,7 +1111,7 @@ pub const Object = struct {
1111 // }1111 // }
11121112
1113 const lhs = wip.arg(0);1113 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);
1115 const is_lt = try wip.icmp(.ult, lhs, rhs, "");1115 const is_lt = try wip.icmp(.ult, lhs, rhs, "");
1116 _ = try wip.ret(is_lt);1116 _ = try wip.ret(is_lt);
1117 try wip.finish();1117 try wip.finish();
...@@ -3121,6 +3121,10 @@ pub const Object = struct {...@@ -3121,6 +3121,10 @@ pub const Object = struct {
3121 return variable_index;3121 return variable_index;
3122 }3122 }
31233123
3124 fn errorIntType(o: *Object) Allocator.Error!Builder.Type {
3125 return o.builder.intType(o.module.errorSetBits());
3126 }
3127
3124 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {3128 fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
3125 const ty = try o.lowerTypeInner(t);3129 const ty = try o.lowerTypeInner(t);
3126 const mod = o.module;3130 const mod = o.module;
...@@ -3192,7 +3196,7 @@ pub const Object = struct {...@@ -3192,7 +3196,7 @@ pub const Object = struct {
3192 .bool_type => .i1,3196 .bool_type => .i1,
3193 .void_type => .void,3197 .void_type => .void,
3194 .type_type => unreachable,3198 .type_type => unreachable,
3195 .anyerror_type => Builder.Type.err_int,3199 .anyerror_type => try o.errorIntType(),
3196 .comptime_int_type,3200 .comptime_int_type,
3197 .comptime_float_type,3201 .comptime_float_type,
3198 .noreturn_type,3202 .noreturn_type,
...@@ -3213,7 +3217,7 @@ pub const Object = struct {...@@ -3213,7 +3217,7 @@ pub const Object = struct {
3213 .optional_noreturn_type => unreachable,3217 .optional_noreturn_type => unreachable,
3214 .anyerror_void_error_union_type,3218 .anyerror_void_error_union_type,
3215 .adhoc_inferred_error_set_type,3219 .adhoc_inferred_error_set_type,
3216 => Builder.Type.err_int,3220 => try o.errorIntType(),
3217 .generic_poison_type,3221 .generic_poison_type,
3218 .empty_struct_type,3222 .empty_struct_type,
3219 => unreachable,3223 => unreachable,
...@@ -3282,16 +3286,17 @@ pub const Object = struct {...@@ -3282,16 +3286,17 @@ pub const Object = struct {
3282 },3286 },
3283 .anyframe_type => @panic("TODO implement lowerType for AnyFrame types"),3287 .anyframe_type => @panic("TODO implement lowerType for AnyFrame types"),
3284 .error_union_type => |error_union_type| {3288 .error_union_type => |error_union_type| {
3285 const error_type = Builder.Type.err_int;3289 const error_type = try o.errorIntType();
3286 if (!error_union_type.payload_type.toType().hasRuntimeBitsIgnoreComptime(mod))3290 if (!error_union_type.payload_type.toType().hasRuntimeBitsIgnoreComptime(mod))
3287 return error_type;3291 return error_type;
3288 const payload_type = try o.lowerType(error_union_type.payload_type.toType());3292 const payload_type = try o.lowerType(error_union_type.payload_type.toType());
3293 const err_int_ty = try mod.errorIntType();
32893294
3290 const payload_align = error_union_type.payload_type.toType().abiAlignment(mod);3295 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
3293 const payload_size = error_union_type.payload_type.toType().abiSize(mod);3298 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
3296 var fields: [3]Builder.Type = undefined;3301 var fields: [3]Builder.Type = undefined;
3297 var fields_len: usize = 2;3302 var fields_len: usize = 2;
...@@ -3552,7 +3557,7 @@ pub const Object = struct {...@@ -3552,7 +3557,7 @@ pub const Object = struct {
3552 },3557 },
3553 .enum_type => |enum_type| try o.lowerType(enum_type.tag_ty.toType()),3558 .enum_type => |enum_type| try o.lowerType(enum_type.tag_ty.toType()),
3554 .func_type => |func_type| try o.lowerTypeFn(func_type),3559 .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(),
3556 // values, not types3561 // values, not types
3557 .undef,3562 .undef,
3558 .runtime_value,3563 .runtime_value,
...@@ -3735,7 +3740,7 @@ pub const Object = struct {...@@ -3735,7 +3740,7 @@ pub const Object = struct {
3735 },3740 },
3736 .err => |err| {3741 .err => |err| {
3737 const int = try mod.getErrorValue(err.name);3742 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);
3739 return llvm_int;3744 return llvm_int;
3740 },3745 },
3741 .error_union => |error_union| {3746 .error_union => |error_union| {
...@@ -3744,8 +3749,9 @@ pub const Object = struct {...@@ -3744,8 +3749,9 @@ pub const Object = struct {
3744 .ty = ty.errorUnionSet(mod).toIntern(),3749 .ty = ty.errorUnionSet(mod).toIntern(),
3745 .name = err_name,3750 .name = err_name,
3746 } }),3751 } }),
3747 .payload => (try mod.intValue(Type.err_int, 0)).toIntern(),3752 .payload => (try mod.intValue(try mod.errorIntType(), 0)).toIntern(),
3748 };3753 };
3754 const err_int_ty = try mod.errorIntType();
3749 const payload_type = ty.errorUnionPayload(mod);3755 const payload_type = ty.errorUnionPayload(mod);
3750 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {3756 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
3751 // We use the error type directly as the type.3757 // We use the error type directly as the type.
...@@ -3753,7 +3759,7 @@ pub const Object = struct {...@@ -3753,7 +3759,7 @@ pub const Object = struct {
3753 }3759 }
37543760
3755 const payload_align = payload_type.abiAlignment(mod);3761 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);
3757 const llvm_error_value = try o.lowerValue(err_val);3763 const llvm_error_value = try o.lowerValue(err_val);
3758 const llvm_payload_value = try o.lowerValue(switch (error_union.val) {3764 const llvm_payload_value = try o.lowerValue(switch (error_union.val) {
3759 .err_name => try mod.intern(.{ .undef = payload_type.toIntern() }),3765 .err_name => try mod.intern(.{ .undef = payload_type.toIntern() }),
...@@ -4288,8 +4294,9 @@ pub const Object = struct {...@@ -4288,8 +4294,9 @@ pub const Object = struct {
4288 return parent_ptr;4294 return parent_ptr;
4289 }4295 }
42904296
4297 const err_int_ty = try mod.errorIntType();
4291 const payload_align = payload_ty.abiAlignment(mod);4298 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);
4293 const index: u32 = if (payload_align.compare(.gt, err_align)) 2 else 1;4300 const index: u32 = if (payload_align.compare(.gt, err_align)) 2 else 1;
4294 return o.builder.gepConst(.inbounds, try o.lowerType(eu_ty), parent_ptr, null, &.{4301 return o.builder.gepConst(.inbounds, try o.lowerType(eu_ty), parent_ptr, null, &.{
4295 try o.builder.intConst(.i32, 0), try o.builder.intConst(.i32, index),4302 try o.builder.intConst(.i32, 0), try o.builder.intConst(.i32, index),
...@@ -5404,7 +5411,7 @@ pub const FuncGen = struct {...@@ -5404,7 +5411,7 @@ pub const FuncGen = struct {
5404 // Functions with an empty error set are emitted with an error code5411 // Functions with an empty error set are emitted with an error code
5405 // return type and return zero so they can be function pointers coerced5412 // return type and return zero so they can be function pointers coerced
5406 // to functions that return anyerror.5413 // 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));
5408 } else {5415 } else {
5409 _ = try self.wip.retVoid();5416 _ = try self.wip.retVoid();
5410 }5417 }
...@@ -5446,7 +5453,7 @@ pub const FuncGen = struct {...@@ -5446,7 +5453,7 @@ pub const FuncGen = struct {
5446 // Functions with an empty error set are emitted with an error code5453 // Functions with an empty error set are emitted with an error code
5447 // return type and return zero so they can be function pointers coerced5454 // return type and return zero so they can be function pointers coerced
5448 // to functions that return anyerror.5455 // 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));
5450 } else {5457 } else {
5451 _ = try self.wip.retVoid();5458 _ = try self.wip.retVoid();
5452 }5459 }
...@@ -5793,24 +5800,25 @@ pub const FuncGen = struct {...@@ -5793,24 +5800,25 @@ pub const FuncGen = struct {
5793 const payload_ty = err_union_ty.errorUnionPayload(mod);5800 const payload_ty = err_union_ty.errorUnionPayload(mod);
5794 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);5801 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5795 const err_union_llvm_ty = try o.lowerType(err_union_ty);5802 const err_union_llvm_ty = try o.lowerType(err_union_ty);
5803 const error_type = try o.errorIntType();
57965804
5797 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {5805 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
5798 const loaded = loaded: {5806 const loaded = loaded: {
5799 if (!payload_has_bits) {5807 if (!payload_has_bits) {
5800 // TODO add alignment to this load5808 // TODO add alignment to this load
5801 break :loaded if (operand_is_ptr)5809 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, "")
5803 else5811 else
5804 err_union;5812 err_union;
5805 }5813 }
5806 const err_field_index = errUnionErrorOffset(payload_ty, mod);5814 const err_field_index = try errUnionErrorOffset(payload_ty, mod);
5807 if (operand_is_ptr or isByRef(err_union_ty, mod)) {5815 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
5808 const err_field_ptr =5816 const err_field_ptr =
5809 try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, "");5817 try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, "");
5810 // TODO add alignment to this load5818 // TODO add alignment to this load
5811 break :loaded try fg.wip.load(5819 break :loaded try fg.wip.load(
5812 .normal,5820 .normal,
5813 Builder.Type.err_int,5821 error_type,
5814 err_field_ptr,5822 err_field_ptr,
5815 .default,5823 .default,
5816 "",5824 "",
...@@ -5818,7 +5826,7 @@ pub const FuncGen = struct {...@@ -5818,7 +5826,7 @@ pub const FuncGen = struct {
5818 }5826 }
5819 break :loaded try fg.wip.extractValue(err_union, &.{err_field_index}, "");5827 break :loaded try fg.wip.extractValue(err_union, &.{err_field_index}, "");
5820 };5828 };
5821 const zero = try o.builder.intValue(Builder.Type.err_int, 0);5829 const zero = try o.builder.intValue(error_type, 0);
5822 const is_err = try fg.wip.icmp(.ne, loaded, zero, "");5830 const is_err = try fg.wip.icmp(.ne, loaded, zero, "");
58235831
5824 const return_block = try fg.wip.block(1, "TryRet");5832 const return_block = try fg.wip.block(1, "TryRet");
...@@ -5832,7 +5840,7 @@ pub const FuncGen = struct {...@@ -5832,7 +5840,7 @@ pub const FuncGen = struct {
5832 }5840 }
5833 if (is_unused) return .none;5841 if (is_unused) return .none;
5834 if (!payload_has_bits) return if (operand_is_ptr) err_union else .none;5842 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);
5836 if (operand_is_ptr) {5844 if (operand_is_ptr) {
5837 return fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, "");5845 return fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, "");
5838 } else if (isByRef(err_union_ty, mod)) {5846 } else if (isByRef(err_union_ty, mod)) {
...@@ -7058,7 +7066,8 @@ pub const FuncGen = struct {...@@ -7058,7 +7066,8 @@ pub const FuncGen = struct {
7058 const operand_ty = self.typeOf(un_op);7066 const operand_ty = self.typeOf(un_op);
7059 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;7067 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
7060 const payload_ty = err_union_ty.errorUnionPayload(mod);7068 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
7063 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {7072 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
7064 const val: Builder.Constant = switch (cond) {7073 const val: Builder.Constant = switch (cond) {
...@@ -7077,13 +7086,13 @@ pub const FuncGen = struct {...@@ -7077,13 +7086,13 @@ pub const FuncGen = struct {
7077 return self.wip.icmp(cond, loaded, zero, "");7086 return self.wip.icmp(cond, loaded, zero, "");
7078 }7087 }
70797088
7080 const err_field_index = errUnionErrorOffset(payload_ty, mod);7089 const err_field_index = try errUnionErrorOffset(payload_ty, mod);
70817090
7082 const loaded = if (operand_is_ptr or isByRef(err_union_ty, mod)) loaded: {7091 const loaded = if (operand_is_ptr or isByRef(err_union_ty, mod)) loaded: {
7083 const err_union_llvm_ty = try o.lowerType(err_union_ty);7092 const err_union_llvm_ty = try o.lowerType(err_union_ty);
7084 const err_field_ptr =7093 const err_field_ptr =
7085 try self.wip.gepStruct(err_union_llvm_ty, operand, err_field_index, "");7094 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, "");
7087 } else try self.wip.extractValue(operand, &.{err_field_index}, "");7096 } else try self.wip.extractValue(operand, &.{err_field_index}, "");
7088 return self.wip.icmp(cond, loaded, zero, "");7097 return self.wip.icmp(cond, loaded, zero, "");
7089 }7098 }
...@@ -7178,7 +7187,7 @@ pub const FuncGen = struct {...@@ -7178,7 +7187,7 @@ pub const FuncGen = struct {
7178 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {7187 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
7179 return if (operand_is_ptr) operand else .none;7188 return if (operand_is_ptr) operand else .none;
7180 }7189 }
7181 const offset = errUnionPayloadOffset(payload_ty, mod);7190 const offset = try errUnionPayloadOffset(payload_ty, mod);
7182 const err_union_llvm_ty = try o.lowerType(err_union_ty);7191 const err_union_llvm_ty = try o.lowerType(err_union_ty);
7183 if (operand_is_ptr) {7192 if (operand_is_ptr) {
7184 return self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");7193 return self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");
...@@ -7205,27 +7214,28 @@ pub const FuncGen = struct {...@@ -7205,27 +7214,28 @@ pub const FuncGen = struct {
7205 const ty_op = self.air.instructions.items(.data)[inst].ty_op;7214 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7206 const operand = try self.resolveInst(ty_op.operand);7215 const operand = try self.resolveInst(ty_op.operand);
7207 const operand_ty = self.typeOf(ty_op.operand);7216 const operand_ty = self.typeOf(ty_op.operand);
7217 const error_type = try o.errorIntType();
7208 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;7218 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
7209 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {7219 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
7210 if (operand_is_ptr) {7220 if (operand_is_ptr) {
7211 return operand;7221 return operand;
7212 } else {7222 } else {
7213 return o.builder.intValue(Builder.Type.err_int, 0);7223 return o.builder.intValue(error_type, 0);
7214 }7224 }
7215 }7225 }
72167226
7217 const payload_ty = err_union_ty.errorUnionPayload(mod);7227 const payload_ty = err_union_ty.errorUnionPayload(mod);
7218 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {7228 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
7219 if (!operand_is_ptr) return operand;7229 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, "");
7221 }7231 }
72227232
7223 const offset = errUnionErrorOffset(payload_ty, mod);7233 const offset = try errUnionErrorOffset(payload_ty, mod);
72247234
7225 if (operand_is_ptr or isByRef(err_union_ty, mod)) {7235 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
7226 const err_union_llvm_ty = try o.lowerType(err_union_ty);7236 const err_union_llvm_ty = try o.lowerType(err_union_ty);
7227 const err_field_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");7237 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, "");
7229 }7239 }
72307240
7231 return self.wip.extractValue(operand, &.{offset}, "");7241 return self.wip.extractValue(operand, &.{offset}, "");
...@@ -7239,15 +7249,16 @@ pub const FuncGen = struct {...@@ -7239,15 +7249,16 @@ pub const FuncGen = struct {
7239 const err_union_ty = self.typeOf(ty_op.operand).childType(mod);7249 const err_union_ty = self.typeOf(ty_op.operand).childType(mod);
72407250
7241 const payload_ty = err_union_ty.errorUnionPayload(mod);7251 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);
7243 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {7253 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
7244 _ = try self.wip.store(.normal, non_error_val, operand, .default);7254 _ = try self.wip.store(.normal, non_error_val, operand, .default);
7245 return operand;7255 return operand;
7246 }7256 }
7247 const err_union_llvm_ty = try o.lowerType(err_union_ty);7257 const err_union_llvm_ty = try o.lowerType(err_union_ty);
7248 {7258 {
7249 const error_alignment = Type.err_int.abiAlignment(mod).toLlvm();7259 const err_int_ty = try mod.errorIntType();
7250 const error_offset = errUnionErrorOffset(payload_ty, mod);7260 const error_alignment = err_int_ty.abiAlignment(mod).toLlvm();
7261 const error_offset = try errUnionErrorOffset(payload_ty, mod);
7251 // First set the non-error value.7262 // First set the non-error value.
7252 const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, "");7263 const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, "");
7253 _ = try self.wip.store(.normal, non_error_val, non_null_ptr, error_alignment);7264 _ = try self.wip.store(.normal, non_error_val, non_null_ptr, error_alignment);
...@@ -7255,7 +7266,7 @@ pub const FuncGen = struct {...@@ -7255,7 +7266,7 @@ pub const FuncGen = struct {
7255 // Then return the payload pointer (only if it is used).7266 // Then return the payload pointer (only if it is used).
7256 if (self.liveness.isUnused(inst)) return .none;7267 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);
7259 return self.wip.gepStruct(err_union_llvm_ty, operand, payload_offset, "");7270 return self.wip.gepStruct(err_union_llvm_ty, operand, payload_offset, "");
7260 }7271 }
72617272
...@@ -7358,11 +7369,11 @@ pub const FuncGen = struct {...@@ -7358,11 +7369,11 @@ pub const FuncGen = struct {
7358 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {7369 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
7359 return operand;7370 return operand;
7360 }7371 }
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);
7362 const err_un_llvm_ty = try o.lowerType(err_un_ty);7373 const err_un_llvm_ty = try o.lowerType(err_un_ty);
73637374
7364 const payload_offset = errUnionPayloadOffset(payload_ty, mod);7375 const payload_offset = try errUnionPayloadOffset(payload_ty, mod);
7365 const error_offset = errUnionErrorOffset(payload_ty, mod);7376 const error_offset = try errUnionErrorOffset(payload_ty, mod);
7366 if (isByRef(err_un_ty, mod)) {7377 if (isByRef(err_un_ty, mod)) {
7367 const directReturn = self.isNextRet(body_tail);7378 const directReturn = self.isNextRet(body_tail);
7368 const result_ptr = if (directReturn)7379 const result_ptr = if (directReturn)
...@@ -7374,7 +7385,8 @@ pub const FuncGen = struct {...@@ -7374,7 +7385,8 @@ pub const FuncGen = struct {
7374 };7385 };
73757386
7376 const err_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, error_offset, "");7387 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();
7378 _ = try self.wip.store(.normal, ok_err_code, err_ptr, error_alignment);7390 _ = try self.wip.store(.normal, ok_err_code, err_ptr, error_alignment);
7379 const payload_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, payload_offset, "");7391 const payload_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, payload_offset, "");
7380 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);7392 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
...@@ -7398,8 +7410,8 @@ pub const FuncGen = struct {...@@ -7398,8 +7410,8 @@ pub const FuncGen = struct {
7398 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return operand;7410 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return operand;
7399 const err_un_llvm_ty = try o.lowerType(err_un_ty);7411 const err_un_llvm_ty = try o.lowerType(err_un_ty);
74007412
7401 const payload_offset = errUnionPayloadOffset(payload_ty, mod);7413 const payload_offset = try errUnionPayloadOffset(payload_ty, mod);
7402 const error_offset = errUnionErrorOffset(payload_ty, mod);7414 const error_offset = try errUnionErrorOffset(payload_ty, mod);
7403 if (isByRef(err_un_ty, mod)) {7415 if (isByRef(err_un_ty, mod)) {
7404 const directReturn = self.isNextRet(body_tail);7416 const directReturn = self.isNextRet(body_tail);
7405 const result_ptr = if (directReturn)7417 const result_ptr = if (directReturn)
...@@ -7411,7 +7423,8 @@ pub const FuncGen = struct {...@@ -7411,7 +7423,8 @@ pub const FuncGen = struct {
7411 };7423 };
74127424
7413 const err_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, error_offset, "");7425 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();
7415 _ = try self.wip.store(.normal, operand, err_ptr, error_alignment);7428 _ = try self.wip.store(.normal, operand, err_ptr, error_alignment);
7416 const payload_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, payload_offset, "");7429 const payload_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, payload_offset, "");
7417 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);7430 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
...@@ -9368,7 +9381,7 @@ pub const FuncGen = struct {...@@ -9368,7 +9381,7 @@ pub const FuncGen = struct {
93689381
9369 for (names) |name| {9382 for (names) |name| {
9370 const err_int = mod.global_error_set.getIndex(name).?;9383 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);
9372 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);9385 try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
9373 }9386 }
9374 self.wip.cursor = .{ .block = valid_block };9387 self.wip.cursor = .{ .block = valid_block };
...@@ -9550,7 +9563,7 @@ pub const FuncGen = struct {...@@ -9550,7 +9563,7 @@ pub const FuncGen = struct {
9550 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;9563 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
95519564
9552 const function_index = try o.builder.addFunction(9565 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),
9554 name,9567 name,
9555 toLlvmAddressSpace(.generic, o.module.getTarget()),9568 toLlvmAddressSpace(.generic, o.module.getTarget()),
9556 );9569 );
...@@ -10885,7 +10898,7 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu...@@ -10885,7 +10898,7 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
10885 // If the return type is an error set or an error union, then we make this10898 // If the return type is an error set or an error union, then we make this
10886 // anyerror return type instead, so that it can be coerced into a function10899 // anyerror return type instead, so that it can be coerced into a function
10887 // pointer type which has anyerror as the return type.10900 // 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;
10889 }10902 }
10890 const target = mod.getTarget();10903 const target = mod.getTarget();
10891 switch (fn_info.cc) {10904 switch (fn_info.cc) {
...@@ -11638,12 +11651,14 @@ fn buildAllocaInner(...@@ -11638,12 +11651,14 @@ fn buildAllocaInner(
11638 return wip.conv(.unneeded, alloca, .ptr, "");11651 return wip.conv(.unneeded, alloca, .ptr, "");
11639}11652}
1164011653
11641fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 {11654fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) !u1 {
11642 return @intFromBool(Type.err_int.abiAlignment(mod).compare(.gt, payload_ty.abiAlignment(mod)));11655 const err_int_ty = try mod.errorIntType();
11656 return @intFromBool(err_int_ty.abiAlignment(mod).compare(.gt, payload_ty.abiAlignment(mod)));
11643}11657}
1164411658
11645fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u1 {11659fn errUnionErrorOffset(payload_ty: Type, mod: *Module) !u1 {
11646 return @intFromBool(Type.err_int.abiAlignment(mod).compare(.lte, payload_ty.abiAlignment(mod)));11660 const err_int_ty = try mod.errorIntType();
11661 return @intFromBool(err_int_ty.abiAlignment(mod).compare(.lte, payload_ty.abiAlignment(mod)));
11647}11662}
1164811663
11649/// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location11664/// 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) {...@@ -159,7 +159,6 @@ pub const Type = enum(u32) {
159 none = std.math.maxInt(u32),159 none = std.math.maxInt(u32),
160 _,160 _,
161161
162 pub const err_int = Type.i16;
163 pub const ptr_amdgpu_constant =162 pub const ptr_amdgpu_constant =
164 @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));163 @field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));
165164
src/codegen/spirv.zig+3-2
...@@ -742,16 +742,17 @@ const DeclGen = struct {...@@ -742,16 +742,17 @@ const DeclGen = struct {
742 .error_union => |error_union| {742 .error_union => |error_union| {
743 // TODO: Error unions may be constructed with constant instructions if the payload type743 // TODO: Error unions may be constructed with constant instructions if the payload type
744 // allows it. For now, just generate it here regardless.744 // allows it. For now, just generate it here regardless.
745 const err_int_ty = try mod.errorIntType();
745 const err_ty = switch (error_union.val) {746 const err_ty = switch (error_union.val) {
746 .err_name => ty.errorUnionSet(mod),747 .err_name => ty.errorUnionSet(mod),
747 .payload => Type.err_int,748 .payload => err_int_ty,
748 };749 };
749 const err_val = switch (error_union.val) {750 const err_val = switch (error_union.val) {
750 .err_name => |err_name| (try mod.intern(.{ .err = .{751 .err_name => |err_name| (try mod.intern(.{ .err = .{
751 .ty = ty.errorUnionSet(mod).toIntern(),752 .ty = ty.errorUnionSet(mod).toIntern(),
752 .name = err_name,753 .name = err_name,
753 } })).toValue(),754 } })).toValue(),
754 .payload => try mod.intValue(Type.err_int, 0),755 .payload => try mod.intValue(err_int_ty, 0),
755 };756 };
756 const payload_ty = ty.errorUnionPayload(mod);757 const payload_ty = ty.errorUnionPayload(mod);
757 const eu_layout = self.errorUnionLayout(payload_ty);758 const eu_layout = self.errorUnionLayout(payload_ty);
src/main.zig+9
...@@ -421,6 +421,7 @@ const usage_build_generic =...@@ -421,6 +421,7 @@ const usage_build_generic =
421 \\ --deps [dep],[dep],... Set dependency names for the root package421 \\ --deps [dep],[dep],... Set dependency names for the root package
422 \\ dep: [[import=]name]422 \\ dep: [[import=]name]
423 \\ --main-mod-path Set the directory of the root module423 \\ --main-mod-path Set the directory of the root module
424 \\ --error-limit [num] Set the maximum amount of distinct error values
424 \\ -fPIC Force-enable Position Independent Code425 \\ -fPIC Force-enable Position Independent Code
425 \\ -fno-PIC Force-disable Position Independent Code426 \\ -fno-PIC Force-disable Position Independent Code
426 \\ -fPIE Force-enable Position Independent Executable427 \\ -fPIE Force-enable Position Independent Executable
...@@ -911,6 +912,8 @@ fn buildOutputType(...@@ -911,6 +912,8 @@ fn buildOutputType(
911 var error_tracing: ?bool = null;912 var error_tracing: ?bool = null;
912 var pdb_out_path: ?[]const u8 = null;913 var pdb_out_path: ?[]const u8 = null;
913 var dwarf_format: ?std.dwarf.Format = null;914 var dwarf_format: ?std.dwarf.Format = null;
915 var error_limit: ?Module.ErrorInt = null;
916
914 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.917 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
915 // This array is populated by zig cc frontend and then has to be converted to zig-style918 // This array is populated by zig cc frontend and then has to be converted to zig-style
916 // CPU features.919 // CPU features.
...@@ -1040,6 +1043,11 @@ fn buildOutputType(...@@ -1040,6 +1043,11 @@ fn buildOutputType(
1040 root_deps_str = args_iter.nextOrFatal();1043 root_deps_str = args_iter.nextOrFatal();
1041 } else if (mem.eql(u8, arg, "--main-mod-path")) {1044 } else if (mem.eql(u8, arg, "--main-mod-path")) {
1042 main_mod_path = args_iter.nextOrFatal();1045 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 };
1043 } else if (mem.eql(u8, arg, "-cflags")) {1051 } else if (mem.eql(u8, arg, "-cflags")) {
1044 extra_cflags.shrinkRetainingCapacity(0);1052 extra_cflags.shrinkRetainingCapacity(0);
1045 while (true) {1053 while (true) {
...@@ -3546,6 +3554,7 @@ fn buildOutputType(...@@ -3546,6 +3554,7 @@ fn buildOutputType(
3546 .reference_trace = reference_trace,3554 .reference_trace = reference_trace,
3547 .error_tracing = error_tracing,3555 .error_tracing = error_tracing,
3548 .pdb_out_path = pdb_out_path,3556 .pdb_out_path = pdb_out_path,
3557 .error_limit = error_limit,
3549 }) catch |err| switch (err) {3558 }) catch |err| switch (err) {
3550 error.LibCUnavailable => {3559 error.LibCUnavailable => {
3551 const target = target_info.target;3560 const target = target_info.target;
src/type.zig+26-22
...@@ -905,8 +905,11 @@ pub const Type = struct {...@@ -905,8 +905,11 @@ pub const Type = struct {
905 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),905 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
906 .error_union_type => |info| return abiAlignmentAdvancedErrorUnion(ty, mod, strat, info.payload_type.toType()),906 .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 type908 .error_set_type, .inferred_error_set_type => {
909 .error_set_type, .inferred_error_set_type => return .{ .scalar = .@"2" },909 const bits = mod.errorSetBits();
910 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
911 return .{ .scalar = intAbiAlignment(bits, target) };
912 },
910913
911 // represents machine code; not a pointer914 // represents machine code; not a pointer
912 .func_type => |func_type| return .{915 .func_type => |func_type| return .{
...@@ -967,10 +970,11 @@ pub const Type = struct {...@@ -967,10 +970,11 @@ pub const Type = struct {
967 else => return .{ .scalar = .@"16" },970 else => return .{ .scalar = .@"16" },
968 },971 },
969972
970 // TODO revisit this when we have the concept of the error tag type973 .anyerror, .adhoc_inferred_error_set => {
971 .anyerror,974 const bits = mod.errorSetBits();
972 .adhoc_inferred_error_set,975 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
973 => return .{ .scalar = .@"2" },976 return .{ .scalar = intAbiAlignment(bits, target) };
977 },
974978
975 .void,979 .void,
976 .type,980 .type,
...@@ -1284,8 +1288,11 @@ pub const Type = struct {...@@ -1284,8 +1288,11 @@ pub const Type = struct {
12841288
1285 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),1289 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
12861290
1287 // TODO revisit this when we have the concept of the error tag type1291 .error_set_type, .inferred_error_set_type => {
1288 .error_set_type, .inferred_error_set_type => return AbiSizeAdvanced{ .scalar = 2 },1292 const bits = mod.errorSetBits();
1293 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1294 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
1295 },
12891296
1290 .error_union_type => |error_union_type| {1297 .error_union_type => |error_union_type| {
1291 const payload_ty = error_union_type.payload_type.toType();1298 const payload_ty = error_union_type.payload_type.toType();
...@@ -1379,10 +1386,11 @@ pub const Type = struct {...@@ -1379,10 +1386,11 @@ pub const Type = struct {
1379 .enum_literal,1386 .enum_literal,
1380 => return AbiSizeAdvanced{ .scalar = 0 },1387 => return AbiSizeAdvanced{ .scalar = 0 },
13811388
1382 // TODO revisit this when we have the concept of the error tag type1389 .anyerror, .adhoc_inferred_error_set => {
1383 .anyerror,1390 const bits = mod.errorSetBits();
1384 .adhoc_inferred_error_set,1391 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1385 => return AbiSizeAdvanced{ .scalar = 2 },1392 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
1393 },
13861394
1387 .prefetch_options => unreachable, // missing call to resolveTypeFields1395 .prefetch_options => unreachable, // missing call to resolveTypeFields
1388 .export_options => unreachable, // missing call to resolveTypeFields1396 .export_options => unreachable, // missing call to resolveTypeFields
...@@ -1576,8 +1584,7 @@ pub const Type = struct {...@@ -1576,8 +1584,7 @@ pub const Type = struct {
1576 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;1584 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
1577 },1585 },
15781586
1579 // TODO revisit this when we have the concept of the error tag type1587 .error_set_type, .inferred_error_set_type => return mod.errorSetBits(),
1580 .error_set_type, .inferred_error_set_type => return 16,
15811588
1582 .error_union_type => {1589 .error_union_type => {
1583 // Optionals and error unions are not packed so their bitsize1590 // Optionals and error unions are not packed so their bitsize
...@@ -1610,10 +1617,9 @@ pub const Type = struct {...@@ -1610,10 +1617,9 @@ pub const Type = struct {
1610 .bool => return 1,1617 .bool => return 1,
1611 .void => return 0,1618 .void => return 0,
16121619
1613 // TODO revisit this when we have the concept of the error tag type
1614 .anyerror,1620 .anyerror,
1615 .adhoc_inferred_error_set,1621 .adhoc_inferred_error_set,
1616 => return 16,1622 => return mod.errorSetBits(),
16171623
1618 .anyopaque => unreachable,1624 .anyopaque => unreachable,
1619 .type => unreachable,1625 .type => unreachable,
...@@ -2172,8 +2178,7 @@ pub const Type = struct {...@@ -2172,8 +2178,7 @@ pub const Type = struct {
21722178
2173 while (true) switch (ty.toIntern()) {2179 while (true) switch (ty.toIntern()) {
2174 .anyerror_type, .adhoc_inferred_error_set_type => {2180 .anyerror_type, .adhoc_inferred_error_set_type => {
2175 // TODO revisit this when error sets support custom int types2181 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
2176 return .{ .signedness = .unsigned, .bits = 16 };
2177 },2182 },
2178 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },2183 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
2179 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },2184 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
...@@ -2192,8 +2197,9 @@ pub const Type = struct {...@@ -2192,8 +2197,9 @@ pub const Type = struct {
2192 .enum_type => |enum_type| ty = enum_type.tag_ty.toType(),2197 .enum_type => |enum_type| ty = enum_type.tag_ty.toType(),
2193 .vector_type => |vector_type| ty = vector_type.child.toType(),2198 .vector_type => |vector_type| ty = vector_type.child.toType(),
21942199
2195 // TODO revisit this when error sets support custom int types2200 .error_set_type, .inferred_error_set_type => {
2196 .error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = 16 },2201 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
2202 },
21972203
2198 .anon_struct_type => unreachable,2204 .anon_struct_type => unreachable,
21992205
...@@ -3303,8 +3309,6 @@ pub const Type = struct {...@@ -3303,8 +3309,6 @@ pub const Type = struct {
33033309
3304 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };3310 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
33053311
3306 pub const err_int = Type.u16;
3307
3308 pub fn smallestUnsignedBits(max: u64) u16 {3312 pub fn smallestUnsignedBits(max: u64) u16 {
3309 if (max == 0) return 0;3313 if (max == 0) return 0;
3310 const base = std.math.log2(max);3314 const base = std.math.log2(max);
src/value.zig+15-8
...@@ -701,15 +701,20 @@ pub const Value = struct {...@@ -701,15 +701,20 @@ pub const Value = struct {
701 }701 }
702 },702 },
703 .ErrorSet => {703 .ErrorSet => {
704 // TODO revisit this when we have the concept of the error tag type704 const bits = mod.errorSetBits();
705 const Int = u16;705 const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
706
706 const name = switch (ip.indexToKey(val.toIntern())) {707 const name = switch (ip.indexToKey(val.toIntern())) {
707 .err => |err| err.name,708 .err => |err| err.name,
708 .error_union => |error_union| error_union.val.err_name,709 .error_union => |error_union| error_union.val.err_name,
709 else => unreachable,710 else => unreachable,
710 };711 };
711 const int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(name).?));712 var bigint_buffer: BigIntSpace = undefined;
712 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @as(Int, @intCast(int)), endian);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);
713 },718 },
714 .Union => switch (ty.containerLayout(mod)) {719 .Union => switch (ty.containerLayout(mod)) {
715 .Auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already720 .Auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already
...@@ -987,10 +992,12 @@ pub const Value = struct {...@@ -987,10 +992,12 @@ pub const Value = struct {
987 }992 }
988 },993 },
989 .ErrorSet => {994 .ErrorSet => {
990 // TODO revisit this when we have the concept of the error tag type995 const bits = mod.errorSetBits();
991 const Int = u16;996 const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
992 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);997 const int = std.mem.readVarInt(u64, buffer[0..byte_count], endian);
993 const name = mod.global_error_set.keys()[@as(usize, @intCast(int))];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
994 return (try mod.intern(.{ .err = .{1001 return (try mod.intern(.{ .err = .{
995 .ty = ty.toIntern(),1002 .ty = ty.toIntern(),
996 .name = name,1003 .name = name,