mirror of
https://github.com/ziglang/zig.git
synced 2026-02-01 12:13:44 +00:00
parent
3d6e633371
commit
bf61c5c065
@ -739,6 +739,7 @@ pub const InitOptions = struct {
|
||||
pdb_source_path: ?[]const u8 = null,
|
||||
/// (Windows) PDB output path
|
||||
pdb_out_path: ?[]const u8 = null,
|
||||
error_limit: ?Module.ErrorInt = null,
|
||||
};
|
||||
|
||||
fn addModuleTableToCacheHash(
|
||||
@ -1432,6 +1433,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
.local_zir_cache = local_zir_cache,
|
||||
.emit_h = emit_h,
|
||||
.tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
|
||||
.error_limit = options.error_limit orelse (std.math.maxInt(u16) - 1),
|
||||
};
|
||||
try module.init();
|
||||
|
||||
@ -2486,6 +2488,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
|
||||
man.hash.add(comp.bin_file.options.skip_linker_dependencies);
|
||||
man.hash.add(comp.bin_file.options.parent_compilation_link_libc);
|
||||
man.hash.add(mod.emit_h != null);
|
||||
man.hash.add(mod.error_limit);
|
||||
}
|
||||
|
||||
try man.addOptionalFile(comp.bin_file.options.linker_script);
|
||||
@ -2866,6 +2869,10 @@ pub fn totalErrorCount(self: *Compilation) u32 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (module.global_error_set.entries.len - 1 > module.error_limit) {
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
for (module.failed_exports.values()) |value| {
|
||||
try addModuleErrorMsg(module, &bundle, value.*);
|
||||
}
|
||||
|
||||
const actual_error_count = module.global_error_set.entries.len - 1;
|
||||
if (actual_error_count > module.error_limit) {
|
||||
try bundle.addRootErrorMessage(.{
|
||||
.msg = try bundle.printString("module used more errors than possible: used {d}, max {d}", .{
|
||||
actual_error_count, module.error_limit,
|
||||
}),
|
||||
.notes_len = 1,
|
||||
});
|
||||
const notes_start = try bundle.reserveNotes(1);
|
||||
bundle.extra.items[notes_start] = @intFromEnum(try bundle.addErrorMessage(.{
|
||||
.msg = try bundle.printString("use '--error-limit {d}' to increase limit", .{
|
||||
actual_error_count,
|
||||
}),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (bundle.root_list.items.len == 0) {
|
||||
|
||||
@ -137,6 +137,9 @@ deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
|
||||
/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
|
||||
global_error_set: GlobalErrorSet = .{},
|
||||
|
||||
/// Maximum amount of distinct error values, set by --error-limit
|
||||
error_limit: ErrorInt,
|
||||
|
||||
/// Incrementing integer used to compare against the corresponding Decl
|
||||
/// field to determine whether a Decl's status applies to an ongoing update, or a
|
||||
/// previous analysis.
|
||||
@ -5020,6 +5023,11 @@ pub fn getErrorValueFromSlice(
|
||||
return getErrorValue(mod, interned_name);
|
||||
}
|
||||
|
||||
pub fn errorSetBits(mod: *Module) u16 {
|
||||
if (mod.error_limit == 0) return 0;
|
||||
return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error
|
||||
}
|
||||
|
||||
pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {
|
||||
const src_decl = mod.declPtr(block.src_decl);
|
||||
return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, block.wip_capture_scope, typed_value);
|
||||
|
||||
@ -421,6 +421,7 @@ const usage_build_generic =
|
||||
\\ --deps [dep],[dep],... Set dependency names for the root package
|
||||
\\ dep: [[import=]name]
|
||||
\\ --main-mod-path Set the directory of the root module
|
||||
\\ --error-limit [num] Set the maximum amount of distinct error values
|
||||
\\ -fPIC Force-enable Position Independent Code
|
||||
\\ -fno-PIC Force-disable Position Independent Code
|
||||
\\ -fPIE Force-enable Position Independent Executable
|
||||
@ -911,6 +912,8 @@ fn buildOutputType(
|
||||
var error_tracing: ?bool = null;
|
||||
var pdb_out_path: ?[]const u8 = null;
|
||||
var dwarf_format: ?std.dwarf.Format = null;
|
||||
var error_limit: ?Module.ErrorInt = null;
|
||||
|
||||
// e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
|
||||
// This array is populated by zig cc frontend and then has to be converted to zig-style
|
||||
// CPU features.
|
||||
@ -1040,6 +1043,11 @@ fn buildOutputType(
|
||||
root_deps_str = args_iter.nextOrFatal();
|
||||
} else if (mem.eql(u8, arg, "--main-mod-path")) {
|
||||
main_mod_path = args_iter.nextOrFatal();
|
||||
} else if (mem.eql(u8, arg, "--error-limit")) {
|
||||
const next_arg = args_iter.nextOrFatal();
|
||||
error_limit = std.fmt.parseUnsigned(Module.ErrorInt, next_arg, 0) catch |err| {
|
||||
fatal("unable to parse error limit '{s}': {s}", .{ next_arg, @errorName(err) });
|
||||
};
|
||||
} else if (mem.eql(u8, arg, "-cflags")) {
|
||||
extra_cflags.shrinkRetainingCapacity(0);
|
||||
while (true) {
|
||||
@ -3546,6 +3554,7 @@ fn buildOutputType(
|
||||
.reference_trace = reference_trace,
|
||||
.error_tracing = error_tracing,
|
||||
.pdb_out_path = pdb_out_path,
|
||||
.error_limit = error_limit,
|
||||
}) catch |err| switch (err) {
|
||||
error.LibCUnavailable => {
|
||||
const target = target_info.target;
|
||||
|
||||
46
src/type.zig
46
src/type.zig
@ -905,8 +905,11 @@ pub const Type = struct {
|
||||
.opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
|
||||
.error_union_type => |info| return abiAlignmentAdvancedErrorUnion(ty, mod, strat, info.payload_type.toType()),
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.error_set_type, .inferred_error_set_type => return .{ .scalar = .@"2" },
|
||||
.error_set_type, .inferred_error_set_type => {
|
||||
const bits = mod.errorSetBits();
|
||||
if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
|
||||
return .{ .scalar = intAbiAlignment(bits, target) };
|
||||
},
|
||||
|
||||
// represents machine code; not a pointer
|
||||
.func_type => |func_type| return .{
|
||||
@ -967,10 +970,11 @@ pub const Type = struct {
|
||||
else => return .{ .scalar = .@"16" },
|
||||
},
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
=> return .{ .scalar = .@"2" },
|
||||
.anyerror, .adhoc_inferred_error_set => {
|
||||
const bits = mod.errorSetBits();
|
||||
if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
|
||||
return .{ .scalar = intAbiAlignment(bits, target) };
|
||||
},
|
||||
|
||||
.void,
|
||||
.type,
|
||||
@ -1284,8 +1288,11 @@ pub const Type = struct {
|
||||
|
||||
.opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.error_set_type, .inferred_error_set_type => return AbiSizeAdvanced{ .scalar = 2 },
|
||||
.error_set_type, .inferred_error_set_type => {
|
||||
const bits = mod.errorSetBits();
|
||||
if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
|
||||
return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
|
||||
},
|
||||
|
||||
.error_union_type => |error_union_type| {
|
||||
const payload_ty = error_union_type.payload_type.toType();
|
||||
@ -1379,10 +1386,11 @@ pub const Type = struct {
|
||||
.enum_literal,
|
||||
=> return AbiSizeAdvanced{ .scalar = 0 },
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
=> return AbiSizeAdvanced{ .scalar = 2 },
|
||||
.anyerror, .adhoc_inferred_error_set => {
|
||||
const bits = mod.errorSetBits();
|
||||
if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
|
||||
return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
|
||||
},
|
||||
|
||||
.prefetch_options => unreachable, // missing call to resolveTypeFields
|
||||
.export_options => unreachable, // missing call to resolveTypeFields
|
||||
@ -1576,8 +1584,7 @@ pub const Type = struct {
|
||||
return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
|
||||
},
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.error_set_type, .inferred_error_set_type => return 16,
|
||||
.error_set_type, .inferred_error_set_type => return mod.errorSetBits(),
|
||||
|
||||
.error_union_type => {
|
||||
// Optionals and error unions are not packed so their bitsize
|
||||
@ -1610,10 +1617,9 @@ pub const Type = struct {
|
||||
.bool => return 1,
|
||||
.void => return 0,
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.anyerror,
|
||||
.adhoc_inferred_error_set,
|
||||
=> return 16,
|
||||
=> return mod.errorSetBits(),
|
||||
|
||||
.anyopaque => unreachable,
|
||||
.type => unreachable,
|
||||
@ -2172,8 +2178,7 @@ pub const Type = struct {
|
||||
|
||||
while (true) switch (ty.toIntern()) {
|
||||
.anyerror_type, .adhoc_inferred_error_set_type => {
|
||||
// TODO revisit this when error sets support custom int types
|
||||
return .{ .signedness = .unsigned, .bits = 16 };
|
||||
return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
|
||||
},
|
||||
.usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
|
||||
.isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
|
||||
@ -2192,8 +2197,9 @@ pub const Type = struct {
|
||||
.enum_type => |enum_type| ty = enum_type.tag_ty.toType(),
|
||||
.vector_type => |vector_type| ty = vector_type.child.toType(),
|
||||
|
||||
// TODO revisit this when error sets support custom int types
|
||||
.error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = 16 },
|
||||
.error_set_type, .inferred_error_set_type => {
|
||||
return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
|
||||
},
|
||||
|
||||
.anon_struct_type => unreachable,
|
||||
|
||||
|
||||
@ -701,15 +701,20 @@ pub const Value = struct {
|
||||
}
|
||||
},
|
||||
.ErrorSet => {
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
const Int = u16;
|
||||
const bits = mod.errorSetBits();
|
||||
const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
|
||||
|
||||
const name = switch (ip.indexToKey(val.toIntern())) {
|
||||
.err => |err| err.name,
|
||||
.error_union => |error_union| error_union.val.err_name,
|
||||
else => unreachable,
|
||||
};
|
||||
const int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(name).?));
|
||||
std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @as(Int, @intCast(int)), endian);
|
||||
var bigint_buffer: BigIntSpace = undefined;
|
||||
const bigint = BigIntMutable.init(
|
||||
&bigint_buffer.limbs,
|
||||
mod.global_error_set.getIndex(name).?,
|
||||
).toConst();
|
||||
bigint.writeTwosComplement(buffer[0..byte_count], endian);
|
||||
},
|
||||
.Union => switch (ty.containerLayout(mod)) {
|
||||
.Auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already
|
||||
@ -987,10 +992,12 @@ pub const Value = struct {
|
||||
}
|
||||
},
|
||||
.ErrorSet => {
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
const Int = u16;
|
||||
const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);
|
||||
const name = mod.global_error_set.keys()[@as(usize, @intCast(int))];
|
||||
const bits = mod.errorSetBits();
|
||||
const byte_count: u16 = @intCast((@as(u17, bits) + 7) / 8);
|
||||
const int = std.mem.readVarInt(u64, buffer[0..byte_count], endian);
|
||||
const index = (int << @as(u6, @intCast(64 - bits))) >> @as(u6, @intCast(64 - bits));
|
||||
const name = mod.global_error_set.keys()[@intCast(index)];
|
||||
|
||||
return (try mod.intern(.{ .err = .{
|
||||
.ty = ty.toIntern(),
|
||||
.name = name,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user