x86_64: implement error set and enum safety

This is all of the expected 0.14.0 progress on #21530, which can now be
postponed once this commit is merged.

This required rewriting the (un)wrap operations since the original
implementations were extremely buggy.

Also adds an easy way to retrigger Sema OPV bugs so that I don't have to
keep updating #22419 all the time.
This commit is contained in:
Jacob Young 2025-02-13 17:09:21 -05:00
parent 5ab5113077
commit 8159ff8b81
155 changed files with 4834 additions and 4054 deletions

View file

@ -8850,7 +8850,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
// Use `intCast`, since it'll set up the Sema-emitted safety checks for us!
const int_val = try sema.intCast(block, src, int_tag_ty, src, operand, src, true, true);
const result = try block.addBitCast(dest_ty, int_val);
if (zcu.backendSupportsFeature(.is_named_enum_value)) {
if (!dest_ty.isNonexhaustiveEnum(zcu) and zcu.backendSupportsFeature(.is_named_enum_value)) {
const ok = try block.addUnOp(.is_named_enum_value, result);
try sema.addSafetyCheck(block, src, ok, .invalid_enum_value);
}

View file

@ -4190,11 +4190,11 @@ pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type };
pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };
pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
pub const single_const_pointer_to_comptime_int: Type = .{
.ip_index = .single_const_pointer_to_comptime_int_type,
};
pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type };
pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type };
pub const single_const_pointer_to_comptime_int: Type = .{ .ip_index = .single_const_pointer_to_comptime_int_type };
pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type };

File diff suppressed because it is too large Load diff

View file

@ -83,8 +83,10 @@ pub fn generateLazyFunction(
debug_output: link.File.DebugInfoOutput,
) CodeGenError!void {
const zcu = pt.zcu;
const file = Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(&zcu.intern_pool);
const target = zcu.fileByIndex(file).mod.resolved_target.result;
const target = if (Type.fromInterned(lazy_sym.ty).typeDeclInstAllowGeneratedTag(zcu)) |inst_index|
zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.resolved_target.result
else
zcu.getTarget();
switch (target_util.zigBackend(target, false)) {
else => unreachable,
inline .stage2_x86_64, .stage2_riscv64 => |backend| {

View file

@ -726,11 +726,11 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
else => false,
},
.is_named_enum_value => switch (backend) {
.stage2_llvm => true,
.stage2_llvm, .stage2_x86_64 => true,
else => false,
},
.error_set_has_value => switch (backend) {
.stage2_llvm, .stage2_wasm => true,
.stage2_llvm, .stage2_wasm, .stage2_x86_64 => true,
else => false,
},
.field_reordering => switch (backend) {

View file

@ -18,5 +18,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -8,7 +8,7 @@ export fn entry() usize {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :4:29: error: invalid operands to binary expression: 'struct' and 'struct'

View file

@ -11,7 +11,7 @@ fn doSomeAsm() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :6:5: error: unable to evaluate comptime expression

View file

@ -8,7 +8,7 @@ export fn foo() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :4:5: error: asm cannot output to const local 'f'

View file

@ -17,7 +17,7 @@ export fn comptimeBuiltinCall() callconv(.Naked) void {
fn f() void {}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:6: error: runtime call not allowed in naked function

View file

@ -4,7 +4,7 @@ export fn entry() void {
fn foo() callconv(.naked) void {}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: unable to call function with calling convention 'naked'

View file

@ -10,7 +10,7 @@ export fn entry1() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:36: error: type 'u32' cannot represent integer value '-1'

View file

@ -5,7 +5,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :4:12: error: operator == not allowed for type '?[3]i32'

View file

@ -13,7 +13,7 @@ export fn baz() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :6:5: error: found compile log statement

View file

@ -10,7 +10,7 @@ fn inner(comptime n: usize) void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :8:9: error: found compile log statement

View file

@ -8,7 +8,7 @@ export fn entry() usize {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:16: error: division by zero here causes undefined behavior

View file

@ -5,7 +5,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:32: error: null pointer casted to type '*i32'

View file

@ -6,7 +6,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:32: error: use of undefined value here causes undefined behavior

View file

@ -6,7 +6,7 @@ export fn foo() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:9: error: expected type 'u16', found '*const [5:0]u8'

View file

@ -15,7 +15,7 @@ fn foo(x: i32) !void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :5:9: error: duplicate switch value

View file

@ -15,7 +15,7 @@ pub export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :9:48: error: caught unexpected error 'InvalidVersion'

View file

@ -13,7 +13,7 @@ fn foo(x: i32) !void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:26: error: switch must handle all possibilities

View file

@ -24,7 +24,7 @@ pub fn main() Error!void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set'

View file

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: exact division produced remainder

View file

@ -8,7 +8,7 @@ export fn entry2() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: primitive integer type 'u65536' exceeds maximum bit width of 65535

View file

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:25: error: exported symbol name cannot be empty

View file

@ -4,7 +4,7 @@ export fn foo(a: *i32) Foo {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:12: error: expected pointer type, found 'i32'

View file

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: exact division produced remainder

View file

@ -7,7 +7,7 @@ fn concat() [16]f32 {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:17: error: expected type '[4]f32', found '[16]f32'

View file

@ -4,7 +4,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :1:1: error: non-extern function has no body

View file

@ -19,7 +19,7 @@ pub export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :18:43: error: value of type 'type' ignored

View file

@ -36,7 +36,7 @@ pub fn is(comptime id: std.builtin.TypeId) TraitFn {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :8:48: error: expected type 'type', found 'bool'

View file

@ -7,7 +7,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :6:9: error: array literal requires address-of operator (&) to coerce to slice type '[]i32'

View file

@ -11,7 +11,7 @@ export fn entry2() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:14: error: expected type 'f32', found 'f64'

View file

@ -13,7 +13,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :11:21: error: 'error.B' not a member of error set 'error{A,C}'

View file

@ -24,7 +24,7 @@ export fn incompatiblePointers4() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :5:9: error: incompatible types: '?@Vector(10, i32)' and '@Vector(11, i32)'

View file

@ -4,7 +4,7 @@ fn main() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:23: error: trailing digit separator

View file

@ -16,7 +16,7 @@ export fn entry4() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: primitive integer type 'u000123' has leading zero

View file

@ -11,7 +11,7 @@ fn loadv(ptr: anytype) i31 {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :10:15: error: unable to determine vector element index of type '*align(16:0:4:?) i31'

View file

@ -24,7 +24,7 @@ export fn foo() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :23:6: error: no field or member function named 'init' in 'tmp.List'

View file

@ -12,7 +12,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :4:26: error: array literal requires address-of operator (&) to coerce to slice type '[][2]f32'

View file

@ -1,5 +1,5 @@
// error
// backend=llvm
// backend=stage2
// target=x86_64-linux
// output_mode=Exe
//

View file

@ -11,7 +11,7 @@ fn foo() ?OtherError!i32 {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :5:34: error: expected type '?error{NextError}!i32', found '?error{OutOfMemory}!i32'

View file

@ -16,7 +16,7 @@ pub export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :15:28: error: expected type '*const fn (type, u8, u8) u32', found '*const fn (void, u8, u8) u32'

View file

@ -43,7 +43,7 @@ export fn entry7() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:31: error: backing integer type 'u32' has bit size 32 but the struct fields have a total bit size of 29

View file

@ -78,7 +78,7 @@ export fn entry14() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :3:12: error: packed structs cannot contain fields of type 'anyerror'

View file

@ -1,7 +1,7 @@
fn main() void {}
// error
// backend=llvm
// backend=stage2
// target=x86_64-linux
// output_mode=Exe
//

View file

@ -3,7 +3,7 @@ export fn entry(a: *i32) usize {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:12: error: expected pointer type, found 'usize'

View file

@ -13,7 +13,7 @@ fn foo(x: i32) !void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:34: error: ranges not allowed when switching on type '@typeInfo(@typeInfo(@TypeOf(tmp.foo)).@"fn".return_type.?).error_union.error_set'

View file

@ -6,7 +6,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: cannot assign to constant

View file

@ -6,7 +6,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: cannot assign to constant

View file

@ -7,7 +7,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: cannot return from naked function

View file

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: operation caused overflow

View file

@ -4,7 +4,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:15: error: exact shift shifted out 1 bits

View file

@ -3,7 +3,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :?:?: error: 10 unused arguments in '{d} {d} {d} {d} {d}'

View file

@ -11,7 +11,7 @@ fn storev(ptr: anytype, val: i31) void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :10:8: error: unable to determine vector element index of type '*align(16:0:4:?) i31'

View file

@ -8,7 +8,7 @@ fn foo() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :6:9: error: cannot suspend inside suspend block

View file

@ -20,7 +20,7 @@ export fn entry() usize {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :14:14: error: unreachable else prong; all cases already handled

View file

@ -7,7 +7,7 @@ export fn entry() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:11: error: unable to evaluate comptime expression

View file

@ -21,7 +21,7 @@ pub export fn simple() void {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :7:14: error: unreachable else prong; all cases already handled

View file

@ -19,7 +19,7 @@ comptime {
}
// error
// backend=llvm
// backend=stage2
// target=native
//
// :2:5: error: runtime safety check not allowed in naked function

View file

@ -23,7 +23,7 @@ pub export fn entry2() void {
}
// error
// backend=llvm
// backend=stage2,llvm
// target=native
//
// :6:20: error: cannot @bitCast to '[]i32'

View file

@ -7,7 +7,7 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux-gnu
// link_libc=true
//

View file

@ -14,5 +14,5 @@ fn foo(comptime info: std.builtin.Type) !void {
// run
// is_test=true
// backend=llvm
// backend=stage2,llvm
//

View file

@ -36,5 +36,5 @@ fn assert(ok: bool) void {
// TODO: enable this for native backend
// run
// backend=llvm
// backend=stage2,llvm
// target=aarch64-linux,aarch64-macos

View file

@ -7,6 +7,6 @@ pub fn main() void {
// compile
// output_mode=Exe
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View file

@ -8,6 +8,6 @@ pub fn main() void {
// compile
// output_mode=Exe
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View file

@ -11,6 +11,6 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View file

@ -5,7 +5,7 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
// link_libc=true
//

View file

@ -4,6 +4,6 @@ pub fn main() void {
}
// compile
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View file

@ -44,6 +44,6 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=x86_64-linux,x86_64-macos
//

View file

@ -18,5 +18,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -7,5 +7,5 @@ pub fn main() void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -21,5 +21,5 @@ fn foo(bytes: []u8) u32 {
return int_slice[0];
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -22,5 +22,5 @@ fn bar(a: u2) Foo {
fn baz(_: Foo) void {}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -19,5 +19,5 @@ pub fn main() u8 {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -19,5 +19,5 @@ pub fn main() u8 {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -17,5 +17,5 @@ fn foo(set1: Set1) Set2 {
return @errorCast(set1);
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -16,5 +16,5 @@ fn foo() anyerror!i32 {
return error.Bar;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -18,5 +18,5 @@ fn bar(one: u1, not_zero: i32) void {
_ = x;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -16,5 +16,5 @@ fn bar(a: f32) i8 {
}
fn baz(_: i8) void {}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -16,5 +16,5 @@ fn bar(a: f32) u8 {
}
fn baz(_: u8) void {}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -16,5 +16,5 @@ fn bar(a: f32) u8 {
}
fn baz(_: u8) void {}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -15,5 +15,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -15,5 +15,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -15,5 +15,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -22,5 +22,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -23,5 +23,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -15,5 +15,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -15,5 +15,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -23,5 +23,5 @@ fn bar(f: *Foo) void {
f.float = 12.34;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -12,5 +12,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -17,5 +17,5 @@ fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
return std.mem.bytesAsSlice(i32, slice);
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -15,5 +15,5 @@ fn bar(x: u16) anyerror {
return @errorFromInt(x);
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -17,5 +17,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -17,5 +17,5 @@ fn divExact(a: i32, b: i32) i32 {
return @divExact(a, b);
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -21,5 +21,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -20,5 +20,5 @@ pub fn main() !void {
return error.TestFailed;
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -17,5 +17,5 @@ pub fn main() !void {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

View file

@ -19,5 +19,5 @@ fn add(a: u16, b: u16) u16 {
}
// run
// backend=llvm
// backend=stage2,llvm
// target=native

Some files were not shown because too many files have changed in this diff Show more