mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
Merge pull request #17651 from Vexu/error-limit
Make distinct error limit configurable (attempt #2)
This commit is contained in:
commit
94d61ce964
@ -5373,8 +5373,9 @@ test "fn reflection" {
|
||||
gets assigned the same integer value.
|
||||
</p>
|
||||
<p>
|
||||
The number of unique error values across the entire compilation should determine the size of the error set type.
|
||||
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>.
|
||||
The error set type defaults to a {#syntax#}u16{#endsyntax#}, though if the maximum number of distinct
|
||||
error values is provided via the <kbd>--error-limit [num]</kbd> command line parameter an integer type
|
||||
with the minimum number of bits required to represent all of the error values will be used.
|
||||
</p>
|
||||
<p>
|
||||
You can {#link|coerce|Type Coercion#} an error from a subset to a superset:
|
||||
@ -8373,7 +8374,7 @@ test "main" {
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@errorFromInt#}
|
||||
<pre>{#syntax#}@errorFromInt(value: std.meta.Int(.unsigned, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre>
|
||||
<pre>{#syntax#}@errorFromInt(value: std.meta.Int(.unsigned, @bitSizeOf(anyerror))) anyerror{#endsyntax#}</pre>
|
||||
<p>
|
||||
Converts from the integer representation of an error into {#link|The Global Error Set#} type.
|
||||
</p>
|
||||
@ -8694,7 +8695,7 @@ test "integer cast panic" {
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@intFromError#}
|
||||
<pre>{#syntax#}@intFromError(err: anytype) std.meta.Int(.unsigned, @sizeOf(anyerror) * 8){#endsyntax#}</pre>
|
||||
<pre>{#syntax#}@intFromError(err: anytype) std.meta.Int(.unsigned, @bitSizeOf(anyerror)){#endsyntax#}</pre>
|
||||
<p>
|
||||
Supports the following types:
|
||||
</p>
|
||||
|
||||
@ -8432,7 +8432,7 @@ fn builtinCall(
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.error_from_int => {
|
||||
const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[0]);
|
||||
const operand = try expr(gz, scope, .{ .rl = .none }, params[0]);
|
||||
const result = try gz.addExtendedPayload(.error_from_int, Zir.Inst.UnNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.operand = operand,
|
||||
|
||||
@ -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);
|
||||
@ -5898,6 +5906,10 @@ pub fn intType(mod: *Module, signedness: std.builtin.Signedness, bits: u16) Allo
|
||||
} })).toType();
|
||||
}
|
||||
|
||||
pub fn errorIntType(mod: *Module) std.mem.Allocator.Error!Type {
|
||||
return mod.intType(.unsigned, mod.errorSetBits());
|
||||
}
|
||||
|
||||
pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type {
|
||||
const i = try intern(mod, .{ .array_type = info });
|
||||
return i.toType();
|
||||
|
||||
21
src/Sema.zig
21
src/Sema.zig
@ -8404,14 +8404,15 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
|
||||
const uncasted_operand = try sema.resolveInst(extra.operand);
|
||||
const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src);
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
|
||||
if (try sema.resolveMaybeUndefVal(operand)) |val| {
|
||||
if (val.isUndef(mod)) {
|
||||
return mod.undefRef(Type.err_int);
|
||||
return mod.undefRef(err_int_ty);
|
||||
}
|
||||
const err_name = ip.indexToKey(val.toIntern()).err.name;
|
||||
return Air.internedToRef((try mod.intValue(
|
||||
Type.err_int,
|
||||
err_int_ty,
|
||||
try mod.getErrorValue(err_name),
|
||||
)).toIntern());
|
||||
}
|
||||
@ -8422,10 +8423,10 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
|
||||
else => |err_set_ty_index| {
|
||||
const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
|
||||
switch (names.len) {
|
||||
0 => return Air.internedToRef((try mod.intValue(Type.err_int, 0)).toIntern()),
|
||||
0 => return Air.internedToRef((try mod.intValue(err_int_ty, 0)).toIntern()),
|
||||
1 => {
|
||||
const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?);
|
||||
return mod.intRef(Type.err_int, int);
|
||||
return mod.intRef(err_int_ty, int);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
@ -8433,7 +8434,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, operand_src);
|
||||
return block.addBitCast(Type.err_int, operand);
|
||||
return block.addBitCast(err_int_ty, operand);
|
||||
}
|
||||
|
||||
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
|
||||
const src = LazySrcLoc.nodeOffset(extra.node);
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
|
||||
const uncasted_operand = try sema.resolveInst(extra.operand);
|
||||
const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src);
|
||||
|
||||
if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
|
||||
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
|
||||
try sema.requireRuntimeBlock(block, src, operand_src);
|
||||
if (block.wantSafety()) {
|
||||
const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand);
|
||||
const zero_val = Air.internedToRef((try mod.intValue(Type.err_int, 0)).toIntern());
|
||||
const zero_val = Air.internedToRef((try mod.intValue(err_int_ty, 0)).toIntern());
|
||||
const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);
|
||||
const ok = try block.addBinOp(.bool_and, is_lt_len, is_non_zero);
|
||||
try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
|
||||
@ -21919,10 +21921,11 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, operand_src);
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) {
|
||||
if (dest_tag == .ErrorUnion) {
|
||||
const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);
|
||||
const err_int = try block.addBitCast(Type.err_int, err_code);
|
||||
const err_int = try block.addBitCast(err_int_ty, err_code);
|
||||
const zero_u16 = Air.internedToRef(try mod.intern(.{
|
||||
.int = .{ .ty = .u16_type, .storage = .{ .u64 = 0 } },
|
||||
}));
|
||||
@ -21938,7 +21941,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
|
||||
try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
|
||||
}
|
||||
} else {
|
||||
const err_int_inst = try block.addBitCast(Type.err_int, operand);
|
||||
const err_int_inst = try block.addBitCast(err_int_ty, operand);
|
||||
const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
|
||||
try sema.addSafetyCheck(block, src, ok, .invalid_error_code);
|
||||
}
|
||||
|
||||
@ -3302,6 +3302,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
|
||||
return WValue{ .imm32 = int };
|
||||
},
|
||||
.error_union => |error_union| {
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const err_tv: TypedValue = switch (error_union.val) {
|
||||
.err_name => |err_name| .{
|
||||
.ty = ty.errorUnionSet(mod),
|
||||
@ -3311,8 +3312,8 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
|
||||
} })).toValue(),
|
||||
},
|
||||
.payload => .{
|
||||
.ty = Type.err_int,
|
||||
.val = try mod.intValue(Type.err_int, 0),
|
||||
.ty = err_int_ty,
|
||||
.val = try mod.intValue(err_int_ty, 0),
|
||||
},
|
||||
};
|
||||
const payload_type = ty.errorUnionPayload(mod);
|
||||
@ -3711,8 +3712,10 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
const errors_len = WValue{ .memory = sym_index };
|
||||
|
||||
try func.emitWValue(operand);
|
||||
const errors_len_val = try func.load(errors_len, Type.err_int, 0);
|
||||
const result = try func.cmp(.stack, errors_len_val, Type.err_int, .lt);
|
||||
const mod = func.bin_file.base.options.module.?;
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const errors_len_val = try func.load(errors_len, err_int_ty, 0);
|
||||
const result = try func.cmp(.stack, errors_len_val, err_int_ty, .lt);
|
||||
|
||||
return func.finishAir(inst, try result.toLocal(func, Type.bool), &.{un_op});
|
||||
}
|
||||
|
||||
@ -1054,6 +1054,7 @@ pub fn genTypedValue(
|
||||
const payload_type = typed_value.ty.errorUnionPayload(mod);
|
||||
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
// We use the error type directly as the type.
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {
|
||||
.err_name => |err_name| return genTypedValue(bin_file, src_loc, .{
|
||||
.ty = err_type,
|
||||
@ -1063,8 +1064,8 @@ pub fn genTypedValue(
|
||||
} })).toValue(),
|
||||
}, owner_decl_index),
|
||||
.payload => return genTypedValue(bin_file, src_loc, .{
|
||||
.ty = Type.err_int,
|
||||
.val = try mod.intValue(Type.err_int, 0),
|
||||
.ty = err_int_ty,
|
||||
.val = try mod.intValue(err_int_ty, 0),
|
||||
}, owner_decl_index),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1038,6 +1038,7 @@ pub const DeclGen = struct {
|
||||
.error_union => |error_union| {
|
||||
const payload_ty = ty.errorUnionPayload(mod);
|
||||
const error_ty = ty.errorUnionSet(mod);
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
switch (error_union.val) {
|
||||
.err_name => |err_name| return dg.renderValue(
|
||||
@ -1051,8 +1052,8 @@ pub const DeclGen = struct {
|
||||
),
|
||||
.payload => return dg.renderValue(
|
||||
writer,
|
||||
Type.err_int,
|
||||
try mod.intValue(Type.err_int, 0),
|
||||
err_int_ty,
|
||||
try mod.intValue(err_int_ty, 0),
|
||||
location,
|
||||
),
|
||||
}
|
||||
@ -1087,8 +1088,8 @@ pub const DeclGen = struct {
|
||||
),
|
||||
.payload => try dg.renderValue(
|
||||
writer,
|
||||
Type.err_int,
|
||||
try mod.intValue(Type.err_int, 0),
|
||||
err_int_ty,
|
||||
try mod.intValue(err_int_ty, 0),
|
||||
location,
|
||||
),
|
||||
}
|
||||
@ -1244,7 +1245,7 @@ pub const DeclGen = struct {
|
||||
payload_ty,
|
||||
switch (opt.val) {
|
||||
.none => switch (payload_ty.zigTypeTag(mod)) {
|
||||
.ErrorSet => try mod.intValue(Type.err_int, 0),
|
||||
.ErrorSet => try mod.intValue(try mod.errorIntType(), 0),
|
||||
.Pointer => try mod.getCoerced(val, payload_ty),
|
||||
else => unreachable,
|
||||
},
|
||||
@ -5196,6 +5197,7 @@ fn airIsNull(
|
||||
const operand_ty = f.typeOf(un_op);
|
||||
const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
|
||||
const payload_ty = optional_ty.optionalChild(mod);
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
|
||||
const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
|
||||
TypedValue{ .ty = Type.bool, .val = Value.true }
|
||||
@ -5203,7 +5205,7 @@ fn airIsNull(
|
||||
// operand is a regular pointer, test `operand !=/== NULL`
|
||||
TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) }
|
||||
else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
|
||||
TypedValue{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, 0) }
|
||||
TypedValue{ .ty = err_int_ty, .val = try mod.intValue(err_int_ty, 0) }
|
||||
else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
|
||||
try writer.writeAll(".ptr");
|
||||
const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
|
||||
@ -5689,8 +5691,10 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
|
||||
else
|
||||
try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
|
||||
else
|
||||
try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Initializer);
|
||||
else {
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Initializer);
|
||||
}
|
||||
}
|
||||
try writer.writeAll(";\n");
|
||||
return local;
|
||||
@ -5811,12 +5815,13 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const error_union_ty = f.typeOf(ty_op.operand).childType(mod);
|
||||
|
||||
const payload_ty = error_union_ty.errorUnionPayload(mod);
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
|
||||
// First, set the non-error value.
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
try f.writeCValueDeref(writer, operand);
|
||||
try writer.writeAll(" = ");
|
||||
try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
|
||||
try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
|
||||
try writer.writeAll(";\n ");
|
||||
|
||||
return operand;
|
||||
@ -5824,7 +5829,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
try reap(f, inst, &.{ty_op.operand});
|
||||
try f.writeCValueDeref(writer, operand);
|
||||
try writer.writeAll(".error = ");
|
||||
try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
|
||||
try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
|
||||
try writer.writeAll(";\n");
|
||||
|
||||
// Then return the payload pointer (only if it is used)
|
||||
@ -5880,7 +5885,8 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
else
|
||||
try f.writeCValueMember(writer, local, .{ .identifier = "error" });
|
||||
try a.assign(f, writer);
|
||||
try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
|
||||
try a.end(f, writer);
|
||||
}
|
||||
return local;
|
||||
@ -5902,6 +5908,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
|
||||
try f.writeCValue(writer, local, .Other);
|
||||
try writer.writeAll(" = ");
|
||||
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
if (!error_ty.errorSetIsEmpty(mod))
|
||||
if (payload_ty.hasRuntimeBits(mod))
|
||||
if (is_ptr)
|
||||
@ -5911,11 +5918,11 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
|
||||
else
|
||||
try f.writeCValue(writer, operand, .Other)
|
||||
else
|
||||
try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
|
||||
try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
|
||||
try writer.writeByte(' ');
|
||||
try writer.writeAll(operator);
|
||||
try writer.writeByte(' ');
|
||||
try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
|
||||
try f.object.dg.renderValue(writer, err_int_ty, try mod.intValue(err_int_ty, 0), .Other);
|
||||
try writer.writeAll(";\n");
|
||||
return local;
|
||||
}
|
||||
|
||||
@ -1111,7 +1111,7 @@ pub const Object = struct {
|
||||
// }
|
||||
|
||||
const lhs = wip.arg(0);
|
||||
const rhs = try o.builder.intValue(Builder.Type.err_int, errors_len);
|
||||
const rhs = try o.builder.intValue(try o.errorIntType(), errors_len);
|
||||
const is_lt = try wip.icmp(.ult, lhs, rhs, "");
|
||||
_ = try wip.ret(is_lt);
|
||||
try wip.finish();
|
||||
@ -3121,6 +3121,10 @@ pub const Object = struct {
|
||||
return variable_index;
|
||||
}
|
||||
|
||||
fn errorIntType(o: *Object) Allocator.Error!Builder.Type {
|
||||
return o.builder.intType(o.module.errorSetBits());
|
||||
}
|
||||
|
||||
fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type {
|
||||
const ty = try o.lowerTypeInner(t);
|
||||
const mod = o.module;
|
||||
@ -3192,7 +3196,7 @@ pub const Object = struct {
|
||||
.bool_type => .i1,
|
||||
.void_type => .void,
|
||||
.type_type => unreachable,
|
||||
.anyerror_type => Builder.Type.err_int,
|
||||
.anyerror_type => try o.errorIntType(),
|
||||
.comptime_int_type,
|
||||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
@ -3213,7 +3217,7 @@ pub const Object = struct {
|
||||
.optional_noreturn_type => unreachable,
|
||||
.anyerror_void_error_union_type,
|
||||
.adhoc_inferred_error_set_type,
|
||||
=> Builder.Type.err_int,
|
||||
=> try o.errorIntType(),
|
||||
.generic_poison_type,
|
||||
.empty_struct_type,
|
||||
=> unreachable,
|
||||
@ -3282,16 +3286,17 @@ pub const Object = struct {
|
||||
},
|
||||
.anyframe_type => @panic("TODO implement lowerType for AnyFrame types"),
|
||||
.error_union_type => |error_union_type| {
|
||||
const error_type = Builder.Type.err_int;
|
||||
const error_type = try o.errorIntType();
|
||||
if (!error_union_type.payload_type.toType().hasRuntimeBitsIgnoreComptime(mod))
|
||||
return error_type;
|
||||
const payload_type = try o.lowerType(error_union_type.payload_type.toType());
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
|
||||
const payload_align = error_union_type.payload_type.toType().abiAlignment(mod);
|
||||
const error_align = Type.err_int.abiAlignment(mod);
|
||||
const error_align = err_int_ty.abiAlignment(mod);
|
||||
|
||||
const payload_size = error_union_type.payload_type.toType().abiSize(mod);
|
||||
const error_size = Type.err_int.abiSize(mod);
|
||||
const error_size = err_int_ty.abiSize(mod);
|
||||
|
||||
var fields: [3]Builder.Type = undefined;
|
||||
var fields_len: usize = 2;
|
||||
@ -3552,7 +3557,7 @@ pub const Object = struct {
|
||||
},
|
||||
.enum_type => |enum_type| try o.lowerType(enum_type.tag_ty.toType()),
|
||||
.func_type => |func_type| try o.lowerTypeFn(func_type),
|
||||
.error_set_type, .inferred_error_set_type => Builder.Type.err_int,
|
||||
.error_set_type, .inferred_error_set_type => try o.errorIntType(),
|
||||
// values, not types
|
||||
.undef,
|
||||
.runtime_value,
|
||||
@ -3735,7 +3740,7 @@ pub const Object = struct {
|
||||
},
|
||||
.err => |err| {
|
||||
const int = try mod.getErrorValue(err.name);
|
||||
const llvm_int = try o.builder.intConst(Builder.Type.err_int, int);
|
||||
const llvm_int = try o.builder.intConst(try o.errorIntType(), int);
|
||||
return llvm_int;
|
||||
},
|
||||
.error_union => |error_union| {
|
||||
@ -3744,8 +3749,9 @@ pub const Object = struct {
|
||||
.ty = ty.errorUnionSet(mod).toIntern(),
|
||||
.name = err_name,
|
||||
} }),
|
||||
.payload => (try mod.intValue(Type.err_int, 0)).toIntern(),
|
||||
.payload => (try mod.intValue(try mod.errorIntType(), 0)).toIntern(),
|
||||
};
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const payload_type = ty.errorUnionPayload(mod);
|
||||
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
// We use the error type directly as the type.
|
||||
@ -3753,7 +3759,7 @@ pub const Object = struct {
|
||||
}
|
||||
|
||||
const payload_align = payload_type.abiAlignment(mod);
|
||||
const error_align = Type.err_int.abiAlignment(mod);
|
||||
const error_align = err_int_ty.abiAlignment(mod);
|
||||
const llvm_error_value = try o.lowerValue(err_val);
|
||||
const llvm_payload_value = try o.lowerValue(switch (error_union.val) {
|
||||
.err_name => try mod.intern(.{ .undef = payload_type.toIntern() }),
|
||||
@ -4288,8 +4294,9 @@ pub const Object = struct {
|
||||
return parent_ptr;
|
||||
}
|
||||
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const payload_align = payload_ty.abiAlignment(mod);
|
||||
const err_align = Type.err_int.abiAlignment(mod);
|
||||
const err_align = err_int_ty.abiAlignment(mod);
|
||||
const index: u32 = if (payload_align.compare(.gt, err_align)) 2 else 1;
|
||||
return o.builder.gepConst(.inbounds, try o.lowerType(eu_ty), parent_ptr, null, &.{
|
||||
try o.builder.intConst(.i32, 0), try o.builder.intConst(.i32, index),
|
||||
@ -5404,7 +5411,7 @@ pub const FuncGen = struct {
|
||||
// Functions with an empty error set are emitted with an error code
|
||||
// return type and return zero so they can be function pointers coerced
|
||||
// to functions that return anyerror.
|
||||
_ = try self.wip.ret(try o.builder.intValue(Builder.Type.err_int, 0));
|
||||
_ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(), 0));
|
||||
} else {
|
||||
_ = try self.wip.retVoid();
|
||||
}
|
||||
@ -5446,7 +5453,7 @@ pub const FuncGen = struct {
|
||||
// Functions with an empty error set are emitted with an error code
|
||||
// return type and return zero so they can be function pointers coerced
|
||||
// to functions that return anyerror.
|
||||
_ = try self.wip.ret(try o.builder.intValue(Builder.Type.err_int, 0));
|
||||
_ = try self.wip.ret(try o.builder.intValue(try o.errorIntType(), 0));
|
||||
} else {
|
||||
_ = try self.wip.retVoid();
|
||||
}
|
||||
@ -5793,24 +5800,25 @@ pub const FuncGen = struct {
|
||||
const payload_ty = err_union_ty.errorUnionPayload(mod);
|
||||
const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
|
||||
const err_union_llvm_ty = try o.lowerType(err_union_ty);
|
||||
const error_type = try o.errorIntType();
|
||||
|
||||
if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
|
||||
const loaded = loaded: {
|
||||
if (!payload_has_bits) {
|
||||
// TODO add alignment to this load
|
||||
break :loaded if (operand_is_ptr)
|
||||
try fg.wip.load(.normal, Builder.Type.err_int, err_union, .default, "")
|
||||
try fg.wip.load(.normal, error_type, err_union, .default, "")
|
||||
else
|
||||
err_union;
|
||||
}
|
||||
const err_field_index = errUnionErrorOffset(payload_ty, mod);
|
||||
const err_field_index = try errUnionErrorOffset(payload_ty, mod);
|
||||
if (operand_is_ptr or isByRef(err_union_ty, mod)) {
|
||||
const err_field_ptr =
|
||||
try fg.wip.gepStruct(err_union_llvm_ty, err_union, err_field_index, "");
|
||||
// TODO add alignment to this load
|
||||
break :loaded try fg.wip.load(
|
||||
.normal,
|
||||
Builder.Type.err_int,
|
||||
error_type,
|
||||
err_field_ptr,
|
||||
.default,
|
||||
"",
|
||||
@ -5818,7 +5826,7 @@ pub const FuncGen = struct {
|
||||
}
|
||||
break :loaded try fg.wip.extractValue(err_union, &.{err_field_index}, "");
|
||||
};
|
||||
const zero = try o.builder.intValue(Builder.Type.err_int, 0);
|
||||
const zero = try o.builder.intValue(error_type, 0);
|
||||
const is_err = try fg.wip.icmp(.ne, loaded, zero, "");
|
||||
|
||||
const return_block = try fg.wip.block(1, "TryRet");
|
||||
@ -5832,7 +5840,7 @@ pub const FuncGen = struct {
|
||||
}
|
||||
if (is_unused) return .none;
|
||||
if (!payload_has_bits) return if (operand_is_ptr) err_union else .none;
|
||||
const offset = errUnionPayloadOffset(payload_ty, mod);
|
||||
const offset = try errUnionPayloadOffset(payload_ty, mod);
|
||||
if (operand_is_ptr) {
|
||||
return fg.wip.gepStruct(err_union_llvm_ty, err_union, offset, "");
|
||||
} else if (isByRef(err_union_ty, mod)) {
|
||||
@ -7058,7 +7066,8 @@ pub const FuncGen = struct {
|
||||
const operand_ty = self.typeOf(un_op);
|
||||
const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
|
||||
const payload_ty = err_union_ty.errorUnionPayload(mod);
|
||||
const zero = try o.builder.intValue(Builder.Type.err_int, 0);
|
||||
const error_type = try o.errorIntType();
|
||||
const zero = try o.builder.intValue(error_type, 0);
|
||||
|
||||
if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
|
||||
const val: Builder.Constant = switch (cond) {
|
||||
@ -7077,13 +7086,13 @@ pub const FuncGen = struct {
|
||||
return self.wip.icmp(cond, loaded, zero, "");
|
||||
}
|
||||
|
||||
const err_field_index = errUnionErrorOffset(payload_ty, mod);
|
||||
const err_field_index = try errUnionErrorOffset(payload_ty, mod);
|
||||
|
||||
const loaded = if (operand_is_ptr or isByRef(err_union_ty, mod)) loaded: {
|
||||
const err_union_llvm_ty = try o.lowerType(err_union_ty);
|
||||
const err_field_ptr =
|
||||
try self.wip.gepStruct(err_union_llvm_ty, operand, err_field_index, "");
|
||||
break :loaded try self.wip.load(.normal, Builder.Type.err_int, err_field_ptr, .default, "");
|
||||
break :loaded try self.wip.load(.normal, error_type, err_field_ptr, .default, "");
|
||||
} else try self.wip.extractValue(operand, &.{err_field_index}, "");
|
||||
return self.wip.icmp(cond, loaded, zero, "");
|
||||
}
|
||||
@ -7178,7 +7187,7 @@ pub const FuncGen = struct {
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
return if (operand_is_ptr) operand else .none;
|
||||
}
|
||||
const offset = errUnionPayloadOffset(payload_ty, mod);
|
||||
const offset = try errUnionPayloadOffset(payload_ty, mod);
|
||||
const err_union_llvm_ty = try o.lowerType(err_union_ty);
|
||||
if (operand_is_ptr) {
|
||||
return self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");
|
||||
@ -7205,27 +7214,28 @@ pub const FuncGen = struct {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const operand_ty = self.typeOf(ty_op.operand);
|
||||
const error_type = try o.errorIntType();
|
||||
const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
|
||||
if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
|
||||
if (operand_is_ptr) {
|
||||
return operand;
|
||||
} else {
|
||||
return o.builder.intValue(Builder.Type.err_int, 0);
|
||||
return o.builder.intValue(error_type, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const payload_ty = err_union_ty.errorUnionPayload(mod);
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
if (!operand_is_ptr) return operand;
|
||||
return self.wip.load(.normal, Builder.Type.err_int, operand, .default, "");
|
||||
return self.wip.load(.normal, error_type, operand, .default, "");
|
||||
}
|
||||
|
||||
const offset = errUnionErrorOffset(payload_ty, mod);
|
||||
const offset = try errUnionErrorOffset(payload_ty, mod);
|
||||
|
||||
if (operand_is_ptr or isByRef(err_union_ty, mod)) {
|
||||
const err_union_llvm_ty = try o.lowerType(err_union_ty);
|
||||
const err_field_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, offset, "");
|
||||
return self.wip.load(.normal, Builder.Type.err_int, err_field_ptr, .default, "");
|
||||
return self.wip.load(.normal, error_type, err_field_ptr, .default, "");
|
||||
}
|
||||
|
||||
return self.wip.extractValue(operand, &.{offset}, "");
|
||||
@ -7239,15 +7249,16 @@ pub const FuncGen = struct {
|
||||
const err_union_ty = self.typeOf(ty_op.operand).childType(mod);
|
||||
|
||||
const payload_ty = err_union_ty.errorUnionPayload(mod);
|
||||
const non_error_val = try o.builder.intValue(Builder.Type.err_int, 0);
|
||||
const non_error_val = try o.builder.intValue(try o.errorIntType(), 0);
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
_ = try self.wip.store(.normal, non_error_val, operand, .default);
|
||||
return operand;
|
||||
}
|
||||
const err_union_llvm_ty = try o.lowerType(err_union_ty);
|
||||
{
|
||||
const error_alignment = Type.err_int.abiAlignment(mod).toLlvm();
|
||||
const error_offset = errUnionErrorOffset(payload_ty, mod);
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const error_alignment = err_int_ty.abiAlignment(mod).toLlvm();
|
||||
const error_offset = try errUnionErrorOffset(payload_ty, mod);
|
||||
// First set the non-error value.
|
||||
const non_null_ptr = try self.wip.gepStruct(err_union_llvm_ty, operand, error_offset, "");
|
||||
_ = try self.wip.store(.normal, non_error_val, non_null_ptr, error_alignment);
|
||||
@ -7255,7 +7266,7 @@ pub const FuncGen = struct {
|
||||
// Then return the payload pointer (only if it is used).
|
||||
if (self.liveness.isUnused(inst)) return .none;
|
||||
|
||||
const payload_offset = errUnionPayloadOffset(payload_ty, mod);
|
||||
const payload_offset = try errUnionPayloadOffset(payload_ty, mod);
|
||||
return self.wip.gepStruct(err_union_llvm_ty, operand, payload_offset, "");
|
||||
}
|
||||
|
||||
@ -7358,11 +7369,11 @@ pub const FuncGen = struct {
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||
return operand;
|
||||
}
|
||||
const ok_err_code = try o.builder.intValue(Builder.Type.err_int, 0);
|
||||
const ok_err_code = try o.builder.intValue(try o.errorIntType(), 0);
|
||||
const err_un_llvm_ty = try o.lowerType(err_un_ty);
|
||||
|
||||
const payload_offset = errUnionPayloadOffset(payload_ty, mod);
|
||||
const error_offset = errUnionErrorOffset(payload_ty, mod);
|
||||
const payload_offset = try errUnionPayloadOffset(payload_ty, mod);
|
||||
const error_offset = try errUnionErrorOffset(payload_ty, mod);
|
||||
if (isByRef(err_un_ty, mod)) {
|
||||
const directReturn = self.isNextRet(body_tail);
|
||||
const result_ptr = if (directReturn)
|
||||
@ -7374,7 +7385,8 @@ pub const FuncGen = struct {
|
||||
};
|
||||
|
||||
const err_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, error_offset, "");
|
||||
const error_alignment = Type.err_int.abiAlignment(mod).toLlvm();
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const error_alignment = err_int_ty.abiAlignment(mod).toLlvm();
|
||||
_ = try self.wip.store(.normal, ok_err_code, err_ptr, error_alignment);
|
||||
const payload_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, payload_offset, "");
|
||||
const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
|
||||
@ -7398,8 +7410,8 @@ pub const FuncGen = struct {
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return operand;
|
||||
const err_un_llvm_ty = try o.lowerType(err_un_ty);
|
||||
|
||||
const payload_offset = errUnionPayloadOffset(payload_ty, mod);
|
||||
const error_offset = errUnionErrorOffset(payload_ty, mod);
|
||||
const payload_offset = try errUnionPayloadOffset(payload_ty, mod);
|
||||
const error_offset = try errUnionErrorOffset(payload_ty, mod);
|
||||
if (isByRef(err_un_ty, mod)) {
|
||||
const directReturn = self.isNextRet(body_tail);
|
||||
const result_ptr = if (directReturn)
|
||||
@ -7411,7 +7423,8 @@ pub const FuncGen = struct {
|
||||
};
|
||||
|
||||
const err_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, error_offset, "");
|
||||
const error_alignment = Type.err_int.abiAlignment(mod).toLlvm();
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const error_alignment = err_int_ty.abiAlignment(mod).toLlvm();
|
||||
_ = try self.wip.store(.normal, operand, err_ptr, error_alignment);
|
||||
const payload_ptr = try self.wip.gepStruct(err_un_llvm_ty, result_ptr, payload_offset, "");
|
||||
const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
|
||||
@ -9368,7 +9381,7 @@ pub const FuncGen = struct {
|
||||
|
||||
for (names) |name| {
|
||||
const err_int = mod.global_error_set.getIndex(name).?;
|
||||
const this_tag_int_value = try o.builder.intConst(Builder.Type.err_int, err_int);
|
||||
const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int);
|
||||
try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
|
||||
}
|
||||
self.wip.cursor = .{ .block = valid_block };
|
||||
@ -9550,7 +9563,7 @@ pub const FuncGen = struct {
|
||||
if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
|
||||
|
||||
const function_index = try o.builder.addFunction(
|
||||
try o.builder.fnType(.i1, &.{Builder.Type.err_int}, .normal),
|
||||
try o.builder.fnType(.i1, &.{try o.errorIntType()}, .normal),
|
||||
name,
|
||||
toLlvmAddressSpace(.generic, o.module.getTarget()),
|
||||
);
|
||||
@ -10885,7 +10898,7 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu
|
||||
// If the return type is an error set or an error union, then we make this
|
||||
// anyerror return type instead, so that it can be coerced into a function
|
||||
// pointer type which has anyerror as the return type.
|
||||
return if (return_type.isError(mod)) Builder.Type.err_int else .void;
|
||||
return if (return_type.isError(mod)) try o.errorIntType() else .void;
|
||||
}
|
||||
const target = mod.getTarget();
|
||||
switch (fn_info.cc) {
|
||||
@ -11638,12 +11651,14 @@ fn buildAllocaInner(
|
||||
return wip.conv(.unneeded, alloca, .ptr, "");
|
||||
}
|
||||
|
||||
fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 {
|
||||
return @intFromBool(Type.err_int.abiAlignment(mod).compare(.gt, payload_ty.abiAlignment(mod)));
|
||||
fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) !u1 {
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
return @intFromBool(err_int_ty.abiAlignment(mod).compare(.gt, payload_ty.abiAlignment(mod)));
|
||||
}
|
||||
|
||||
fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u1 {
|
||||
return @intFromBool(Type.err_int.abiAlignment(mod).compare(.lte, payload_ty.abiAlignment(mod)));
|
||||
fn errUnionErrorOffset(payload_ty: Type, mod: *Module) !u1 {
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
return @intFromBool(err_int_ty.abiAlignment(mod).compare(.lte, payload_ty.abiAlignment(mod)));
|
||||
}
|
||||
|
||||
/// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location
|
||||
|
||||
@ -159,7 +159,6 @@ pub const Type = enum(u32) {
|
||||
none = std.math.maxInt(u32),
|
||||
_,
|
||||
|
||||
pub const err_int = Type.i16;
|
||||
pub const ptr_amdgpu_constant =
|
||||
@field(Type, std.fmt.comptimePrint("ptr{ }", .{AddrSpace.amdgpu.constant}));
|
||||
|
||||
|
||||
@ -742,16 +742,17 @@ const DeclGen = struct {
|
||||
.error_union => |error_union| {
|
||||
// TODO: Error unions may be constructed with constant instructions if the payload type
|
||||
// allows it. For now, just generate it here regardless.
|
||||
const err_int_ty = try mod.errorIntType();
|
||||
const err_ty = switch (error_union.val) {
|
||||
.err_name => ty.errorUnionSet(mod),
|
||||
.payload => Type.err_int,
|
||||
.payload => err_int_ty,
|
||||
};
|
||||
const err_val = switch (error_union.val) {
|
||||
.err_name => |err_name| (try mod.intern(.{ .err = .{
|
||||
.ty = ty.errorUnionSet(mod).toIntern(),
|
||||
.name = err_name,
|
||||
} })).toValue(),
|
||||
.payload => try mod.intValue(Type.err_int, 0),
|
||||
.payload => try mod.intValue(err_int_ty, 0),
|
||||
};
|
||||
const payload_ty = ty.errorUnionPayload(mod);
|
||||
const eu_layout = self.errorUnionLayout(payload_ty);
|
||||
|
||||
@ -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;
|
||||
|
||||
48
src/type.zig
48
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,
|
||||
|
||||
@ -3303,8 +3309,6 @@ pub const Type = struct {
|
||||
|
||||
pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
|
||||
|
||||
pub const err_int = Type.u16;
|
||||
|
||||
pub fn smallestUnsignedBits(max: u64) u16 {
|
||||
if (max == 0) return 0;
|
||||
const base = std.math.log2(max);
|
||||
|
||||
@ -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