authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-24 13:35:10+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-10-21 12:36:29+03:00
logbf61c5c0656e3b2198fb009fe5cc59f55263ceae
treed72d4f475af2d6ba6cbc4080ecb6e8b0d7a24c3d
parent3d6e63337164b42fec4df55687071be38d33dce9

make distinct error limit configurable

Closes #786

5 files changed, 81 insertions(+), 28 deletions(-)

src/Compilation.zig+23
......@@ -739,6 +739,7 @@ pub const InitOptions = struct {
739739 pdb_source_path: ?[]const u8 = null,
740740 /// (Windows) PDB output path
741741 pdb_out_path: ?[]const u8 = null,
742 error_limit: ?Module.ErrorInt = null,
742743};
743744
744745fn addModuleTableToCacheHash(
......@@ -1432,6 +1433,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14321433 .local_zir_cache = local_zir_cache,
14331434 .emit_h = emit_h,
14341435 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
1436 .error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1),
14351437 };
14361438 try module.init();
14371439
......@@ -2486,6 +2488,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
24862488 man.hash.add(comp.bin_file.options.skip_linker_dependencies);
24872489 man.hash.add(comp.bin_file.options.parent_compilation_link_libc);
24882490 man.hash.add(mod.emit_h != null);
2491 man.hash.add(mod.error_limit);
24892492 }
24902493
24912494 try man.addOptionalFile(comp.bin_file.options.linker_script);
......@@ -2866,6 +2869,10 @@ pub fn totalErrorCount(self: *Compilation) u32 {
28662869 }
28672870 }
28682871 }
2872
2873 if (module.global_error_set.entries.len - 1 > module.error_limit) {
2874 total += 1;
2875 }
28692876 }
28702877
28712878 // The "no entry point found" error only counts if there are no semantic analysis errors.
......@@ -3016,6 +3023,22 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
30163023 for (module.failed_exports.values()) |value| {
30173024 try addModuleErrorMsg(module, &bundle, value.*);
30183025 }
3026
3027 const actual_error_count = module.global_error_set.entries.len - 1;
3028 if (actual_error_count > module.error_limit) {
3029 try bundle.addRootErrorMessage(.{
3030 .msg = try bundle.printString("module used more errors than possible: used {d}, max {d}", .{
3031 actual_error_count, module.error_limit,
3032 }),
3033 .notes_len = 1,
3034 });
3035 const notes_start = try bundle.reserveNotes(1);
3036 bundle.extra.items[notes_start] = @intFromEnum(try bundle.addErrorMessage(.{
3037 .msg = try bundle.printString("use '--error-limit {d}' to increase limit", .{
3038 actual_error_count,
3039 }),
3040 }));
3041 }
30193042 }
30203043
30213044 if (bundle.root_list.items.len == 0) {
src/Module.zig+8
......@@ -137,6 +137,9 @@ deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
137137/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
138138global_error_set: GlobalErrorSet = .{},
139139
140/// Maximum amount of distinct error values, set by --error-limit
141error_limit: ErrorInt,
142
140143/// Incrementing integer used to compare against the corresponding Decl
141144/// field to determine whether a Decl's status applies to an ongoing update, or a
142145/// previous analysis.
......@@ -5020,6 +5023,11 @@ pub fn getErrorValueFromSlice(
50205023 return getErrorValue(mod, interned_name);
50215024}
50225025
5026pub fn errorSetBits(mod: *Module) u16 {
5027 if (mod.error_limit == 0) return 0;
5028 return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error
5029}
5030
50235031pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {
50245032 const src_decl = mod.declPtr(block.src_decl);
50255033 return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value);
src/main.zig+9
......@@ -421,6 +421,7 @@ const usage_build_generic =
421421 \\ --deps [dep],[dep],... Set dependency names for the root package
422422 \\ dep: [[import=]name]
423423 \\ --main-mod-path Set the directory of the root module
424 \\ --error-limit [num] Set the maximum amount of distinct error values
424425 \\ -fPIC Force-enable Position Independent Code
425426 \\ -fno-PIC Force-disable Position Independent Code
426427 \\ -fPIE Force-enable Position Independent Executable
......@@ -911,6 +912,8 @@ fn buildOutputType(
911912 var error_tracing: ?bool = null;
912913 var pdb_out_path: ?[]const u8 = null;
913914 var dwarf_format: ?std.dwarf.Format = null;
915 var error_limit: ?Module.ErrorInt = null;
916
914917 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
915918 // This array is populated by zig cc frontend and then has to be converted to zig-style
916919 // CPU features.
......@@ -1040,6 +1043,11 @@ fn buildOutputType(
10401043 root_deps_str = args_iter.nextOrFatal();
10411044 } else if (mem.eql(u8, arg, "--main-mod-path")) {
10421045 main_mod_path = args_iter.nextOrFatal();
1046 } else if (mem.eql(u8, arg, "--error-limit")) {
1047 const next_arg = args_iter.nextOrFatal();
1048 error_limit = std.fmt.parseUnsigned(Module.ErrorInt, next_arg, 0) catch |err| {
1049 fatal("unable to parse error limit '{s}': {s}", .{ next_arg, @errorName(err) });
1050 };
10431051 } else if (mem.eql(u8, arg, "-cflags")) {
10441052 extra_cflags.shrinkRetainingCapacity(0);
10451053 while (true) {
......@@ -3546,6 +3554,7 @@ fn buildOutputType(
35463554 .reference_trace = reference_trace,
35473555 .error_tracing = error_tracing,
35483556 .pdb_out_path = pdb_out_path,
3557 .error_limit = error_limit,
35493558 }) catch |err| switch (err) {
35503559 error.LibCUnavailable => {
35513560 const target = target_info.target;
src/type.zig+26-20
......@@ -905,8 +905,11 @@ pub const Type = struct {
905905 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
906906 .error_union_type => |info| return abiAlignmentAdvancedErrorUnion(ty, mod, strat, info.payload_type.toType()),
907907
908 // TODO revisit this when we have the concept of the error tag type
909 .error_set_type, .inferred_error_set_type => return .{ .scalar = .@"2" },
908 .error_set_type, .inferred_error_set_type => {
909 const bits = mod.errorSetBits();
910 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
911 return .{ .scalar = intAbiAlignment(bits, target) };
912 },
910913
911914 // represents machine code; not a pointer
912915 .func_type => |func_type| return .{
......@@ -967,10 +970,11 @@ pub const Type = struct {
967970 else => return .{ .scalar = .@"16" },
968971 },
969972
970 // TODO revisit this when we have the concept of the error tag type
971 .anyerror,
972 .adhoc_inferred_error_set,
973 => return .{ .scalar = .@"2" },
973 .anyerror, .adhoc_inferred_error_set => {
974 const bits = mod.errorSetBits();
975 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
976 return .{ .scalar = intAbiAlignment(bits, target) };
977 },
974978
975979 .void,
976980 .type,
......@@ -1284,8 +1288,11 @@ pub const Type = struct {
12841288
12851289 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
12861290
1287 // TODO revisit this when we have the concept of the error tag type
1288 .error_set_type, .inferred_error_set_type => return AbiSizeAdvanced{ .scalar = 2 },
1291 .error_set_type, .inferred_error_set_type => {
1292 const bits = mod.errorSetBits();
1293 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1294 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
1295 },
12891296
12901297 .error_union_type => |error_union_type| {
12911298 const payload_ty = error_union_type.payload_type.toType();
......@@ -1379,10 +1386,11 @@ pub const Type = struct {
13791386 .enum_literal,
13801387 => return AbiSizeAdvanced{ .scalar = 0 },
13811388
1382 // TODO revisit this when we have the concept of the error tag type
1383 .anyerror,
1384 .adhoc_inferred_error_set,
1385 => return AbiSizeAdvanced{ .scalar = 2 },
1389 .anyerror, .adhoc_inferred_error_set => {
1390 const bits = mod.errorSetBits();
1391 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1392 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
1393 },
13861394
13871395 .prefetch_options => unreachable, // missing call to resolveTypeFields
13881396 .export_options => unreachable, // missing call to resolveTypeFields
......@@ -1576,8 +1584,7 @@ pub const Type = struct {
15761584 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
15771585 },
15781586
1579 // TODO revisit this when we have the concept of the error tag type
1580 .error_set_type, .inferred_error_set_type => return 16,
1587 .error_set_type, .inferred_error_set_type => return mod.errorSetBits(),
15811588
15821589 .error_union_type => {
15831590 // Optionals and error unions are not packed so their bitsize
......@@ -1610,10 +1617,9 @@ pub const Type = struct {
16101617 .bool => return 1,
16111618 .void => return 0,
16121619
1613 // TODO revisit this when we have the concept of the error tag type
16141620 .anyerror,
16151621 .adhoc_inferred_error_set,
1616 => return 16,
1622 => return mod.errorSetBits(),
16171623
16181624 .anyopaque => unreachable,
16191625 .type => unreachable,
......@@ -2172,8 +2178,7 @@ pub const Type = struct {
21722178
21732179 while (true) switch (ty.toIntern()) {
21742180 .anyerror_type, .adhoc_inferred_error_set_type => {
2175 // TODO revisit this when error sets support custom int types
2176 return .{ .signedness = .unsigned, .bits = 16 };
2181 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
21772182 },
21782183 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
21792184 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
......@@ -2192,8 +2197,9 @@ pub const Type = struct {
21922197 .enum_type => |enum_type| ty = enum_type.tag_ty.toType(),
21932198 .vector_type => |vector_type| ty = vector_type.child.toType(),
21942199
2195 // TODO revisit this when error sets support custom int types
2196 .error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = 16 },
2200 .error_set_type, .inferred_error_set_type => {
2201 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
2202 },
21972203
21982204 .anon_struct_type => unreachable,
21992205
src/value.zig+15-8
......@@ -701,15 +701,20 @@ pub const Value = struct {
701701 }
702702 },
703703 .ErrorSet => {
704 // TODO revisit this when we have the concept of the error tag type
705 const Int = u16;
704 const bits = mod.errorSetBits();
705 const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
706
706707 const name = switch (ip.indexToKey(val.toIntern())) {
707708 .err => |err| err.name,
708709 .error_union => |error_union| error_union.val.err_name,
709710 else => unreachable,
710711 };
711 const int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(name).?));
712 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @as(Int, @intCast(int)), endian);
712 var bigint_buffer: BigIntSpace = undefined;
713 const bigint = BigIntMutable.init(
714 &bigint_buffer.limbs,
715 mod.global_error_set.getIndex(name).?,
716 ).toConst();
717 bigint.writeTwosComplement(buffer[0..byte_count], endian);
713718 },
714719 .Union => switch (ty.containerLayout(mod)) {
715720 .Auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already
......@@ -987,10 +992,12 @@ pub const Value = struct {
987992 }
988993 },
989994 .ErrorSet => {
990 // TODO revisit this when we have the concept of the error tag type
991 const Int = u16;
992 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);
993 const name = mod.global_error_set.keys()[@as(usize, @intCast(int))];
995 const bits = mod.errorSetBits();
996 const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
997 const int = std.mem.readVarInt(u64, buffer[0..byte_count], endian);
998 const index = (int << @as(u6, @intCast(64 - bits))) >> @as(u6, @intCast(64 - bits));
999 const name = mod.global_error_set.keys()[@intCast(index)];
1000
9941001 return (try mod.intern(.{ .err = .{
9951002 .ty = ty.toIntern(),
9961003 .name = name,