| author | |
| committer | |
| log | 94d61ce964cd23fcf46dabeddc19837b4dd3209f |
| tree | 00fc6af0a362d7d5744744e3f5e8008136957401 |
| parent | b82459fa435c366c6af0fee96c3d9b95c24078f9 |
| parent | ed82e4f7ac057286444135dda79fb7c6a579573a |
| signature |
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#} |
| 8374 | 8375 | ||
| 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#} |
| 8695 | 8696 | ||
| 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 path | 740 | /// (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 | }; |
| 743 | 744 | ||
| 744 | fn addModuleTableToCacheHash( | 745 | fn 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(); |
| 1437 | 1439 | ||
| ... | @@ -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 | } |
| 2490 | 2493 | ||
| 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 | } |
| 2870 | 2877 | ||
| 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 | } |
| 3020 | 3043 | ||
| 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. |
| 138 | global_error_set: GlobalErrorSet = .{}, | 138 | global_error_set: GlobalErrorSet = .{}, |
| 139 | 139 | ||
| 140 | /// Maximum amount of distinct error values, set by --error-limit | ||
| 141 | error_limit: ErrorInt, | ||
| 142 | |||
| 140 | /// Incrementing integer used to compare against the corresponding Decl | 143 | /// Incrementing integer used to compare against the corresponding Decl |
| 141 | /// field to determine whether a Decl's status applies to an ongoing update, or a | 144 | /// 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 | } |
| 5022 | 5025 | ||
| 5026 | pub 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 | |||
| 5023 | pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index { | 5031 | pub 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 | } |
| 5900 | 5908 | ||
| 5909 | pub fn errorIntType(mod: *Module) std.mem.Allocator.Error!Type { | ||
| 5910 | return mod.intType(.unsigned, mod.errorSetBits()); | ||
| 5911 | } | ||
| 5912 | |||
| 5901 | pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type { | 5913 | pub 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(); | ||
| 8407 | 8408 | ||
| 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 | } |
| 8434 | 8435 | ||
| 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 | } |
| 8438 | 8439 | ||
| 8439 | fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 8440 | fn 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); | ||
| 8449 | 8451 | ||
| 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 | } |
| 21920 | 21922 | ||
| 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 }; |
| 3712 | 3713 | ||
| 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); | ||
| 3716 | 3719 | ||
| 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(); | ||
| 5199 | 5201 | ||
| 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 | else | 5692 | else |
| 5691 | try f.writeCValueMember(writer, operand, .{ .identifier = "error" }) | 5693 | try f.writeCValueMember(writer, operand, .{ .identifier = "error" }) |
| 5692 | else | 5694 | 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); |
| 5812 | 5816 | ||
| 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(); | ||
| 5814 | 5819 | ||
| 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 "); |
| 5821 | 5826 | ||
| 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"); |
| 5829 | 5834 | ||
| 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 | else | 5885 | 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(" = "); |
| 5904 | 5910 | ||
| 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 | else | 5918 | else |
| 5912 | try f.writeCValue(writer, operand, .Other) | 5919 | try f.writeCValue(writer, operand, .Other) |
| 5913 | else | 5920 | 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 | // } |
| 1112 | 1112 | ||
| 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 | } |
| 3123 | 3123 | ||
| 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(); | ||
| 3289 | 3294 | ||
| 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); |
| 3292 | 3297 | ||
| 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); |
| 3295 | 3300 | ||
| 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 types | 3561 | // 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 | } |
| 3754 | 3760 | ||
| 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 | } |
| 4290 | 4296 | ||
| 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 code | 5411 | // Functions with an empty error set are emitted with an error code |
| 5405 | // return type and return zero so they can be function pointers coerced | 5412 | // 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 code | 5453 | // Functions with an empty error set are emitted with an error code |
| 5447 | // return type and return zero so they can be function pointers coerced | 5454 | // 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(); | ||
| 5796 | 5804 | ||
| 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 load | 5808 | // 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 | else | 5811 | 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 load | 5818 | // 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, ""); |
| 5823 | 5831 | ||
| 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); | ||
| 7062 | 7071 | ||
| 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 | } |
| 7079 | 7088 | ||
| 7080 | const err_field_index = errUnionErrorOffset(payload_ty, mod); | 7089 | const err_field_index = try errUnionErrorOffset(payload_ty, mod); |
| 7081 | 7090 | ||
| 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 | } |
| 7216 | 7226 | ||
| 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 | } |
| 7222 | 7232 | ||
| 7223 | const offset = errUnionErrorOffset(payload_ty, mod); | 7233 | const offset = try errUnionErrorOffset(payload_ty, mod); |
| 7224 | 7234 | ||
| 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 | } |
| 7230 | 7240 | ||
| 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); |
| 7240 | 7250 | ||
| 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; |
| 7257 | 7268 | ||
| 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 | } |
| 7261 | 7272 | ||
| ... | @@ -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); |
| 7363 | 7374 | ||
| 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 | }; |
| 7375 | 7386 | ||
| 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); |
| 7400 | 7412 | ||
| 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 | }; |
| 7412 | 7424 | ||
| 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 { |
| 9368 | 9381 | ||
| 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; |
| 9551 | 9564 | ||
| 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 this | 10898 | // 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 function | 10899 | // 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 | } |
| 11640 | 11653 | ||
| 11641 | fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 { | 11654 | fn 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 | } |
| 11644 | 11658 | ||
| 11645 | fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u1 { | 11659 | fn 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 | } |
| 11648 | 11663 | ||
| 11649 | /// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location | 11664 | /// 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 | _, |
| 161 | 161 | ||
| 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})); |
| 165 | 164 |
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 type | 743 | // 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 package | 421 | \\ --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 module | 423 | \\ --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 Code | 425 | \\ -fPIC Force-enable Position Independent Code |
| 425 | \\ -fno-PIC Force-disable Position Independent Code | 426 | \\ -fno-PIC Force-disable Position Independent Code |
| 426 | \\ -fPIE Force-enable Position Independent Executable | 427 | \\ -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-style | 918 | // 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()), |
| 907 | 907 | ||
| 908 | // TODO revisit this when we have the concept of the error tag type | 908 | .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 | }, | ||
| 910 | 913 | ||
| 911 | // represents machine code; not a pointer | 914 | // 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 | }, |
| 969 | 972 | ||
| 970 | // TODO revisit this when we have the concept of the error tag type | 973 | .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 | }, | ||
| 974 | 978 | ||
| 975 | .void, | 979 | .void, |
| 976 | .type, | 980 | .type, |
| ... | @@ -1284,8 +1288,11 @@ pub const Type = struct { | ... | @@ -1284,8 +1288,11 @@ pub const Type = struct { |
| 1284 | 1288 | ||
| 1285 | .opt_type => return ty.abiSizeAdvancedOptional(mod, strat), | 1289 | .opt_type => return ty.abiSizeAdvancedOptional(mod, strat), |
| 1286 | 1290 | ||
| 1287 | // TODO revisit this when we have the concept of the error tag type | 1291 | .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 | }, | ||
| 1289 | 1296 | ||
| 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 }, |
| 1381 | 1388 | ||
| 1382 | // TODO revisit this when we have the concept of the error tag type | 1389 | .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 | }, | ||
| 1386 | 1394 | ||
| 1387 | .prefetch_options => unreachable, // missing call to resolveTypeFields | 1395 | .prefetch_options => unreachable, // missing call to resolveTypeFields |
| 1388 | .export_options => unreachable, // missing call to resolveTypeFields | 1396 | .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 | }, |
| 1578 | 1586 | ||
| 1579 | // TODO revisit this when we have the concept of the error tag type | 1587 | .error_set_type, .inferred_error_set_type => return mod.errorSetBits(), |
| 1580 | .error_set_type, .inferred_error_set_type => return 16, | ||
| 1581 | 1588 | ||
| 1582 | .error_union_type => { | 1589 | .error_union_type => { |
| 1583 | // Optionals and error unions are not packed so their bitsize | 1590 | // 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, |
| 1612 | 1619 | ||
| 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(), |
| 1617 | 1623 | ||
| 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 { |
| 2172 | 2178 | ||
| 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 types | 2181 | 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(), |
| 2194 | 2199 | ||
| 2195 | // TODO revisit this when error sets support custom int types | 2200 | .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 | }, | ||
| 2197 | 2203 | ||
| 2198 | .anon_struct_type => unreachable, | 2204 | .anon_struct_type => unreachable, |
| 2199 | 2205 | ||
| ... | @@ -3303,8 +3309,6 @@ pub const Type = struct { | ... | @@ -3303,8 +3309,6 @@ pub const Type = struct { |
| 3303 | 3309 | ||
| 3304 | pub const generic_poison: Type = .{ .ip_index = .generic_poison_type }; | 3310 | pub const generic_poison: Type = .{ .ip_index = .generic_poison_type }; |
| 3305 | 3311 | ||
| 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 type | 704 | 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 already | 720 | .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 type | 995 | 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, |