Skip to content

Commit b26e732

Browse files
committed
aarch64: fix error union constants
1 parent 771523c commit b26e732

File tree

4 files changed

+62
-40
lines changed

4 files changed

+62
-40
lines changed

src/codegen/aarch64/Select.zig

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10414,11 +10414,12 @@ pub const Value = struct {
1041410414
} },
1041510415
.error_union => |error_union| {
1041610416
const error_union_type = ip.indexToKey(error_union.ty).error_union_type;
10417+
const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
1041710418
const payload_ty: ZigType = .fromInterned(error_union_type.payload_type);
10418-
if (!ip.isNoReturn(error_union_type.error_set_type) and
10419-
offset == codegen.errUnionErrorOffset(payload_ty, zcu))
10420-
{
10421-
offset = 0;
10419+
const error_set_offset = codegen.errUnionErrorOffset(payload_ty, zcu);
10420+
const error_set_size = error_set_ty.abiSize(zcu);
10421+
if (offset >= error_set_offset and offset + size <= error_set_offset + error_set_size) {
10422+
offset -= error_set_offset;
1042210423
continue :constant_key switch (error_union.val) {
1042310424
.err_name => |err_name| .{ .err = .{
1042410425
.ty = error_union_type.error_set_type,
@@ -10430,15 +10431,18 @@ pub const Value = struct {
1043010431
} },
1043110432
};
1043210433
}
10433-
assert(payload_ty.hasRuntimeBitsIgnoreComptime(zcu));
10434-
offset -= @intCast(codegen.errUnionPayloadOffset(payload_ty, zcu));
10435-
switch (error_union.val) {
10436-
.err_name => continue :constant_key .{ .undef = error_union_type.payload_type },
10437-
.payload => |payload| {
10438-
constant = payload;
10439-
constant_key = ip.indexToKey(payload);
10440-
continue :constant_key constant_key;
10441-
},
10434+
const payload_offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
10435+
const payload_size = payload_ty.abiSize(zcu);
10436+
if (offset >= payload_offset and offset + size <= payload_offset + payload_size) {
10437+
offset -= payload_offset;
10438+
switch (error_union.val) {
10439+
.err_name => continue :constant_key .{ .undef = error_union_type.payload_type },
10440+
.payload => |payload| {
10441+
constant = payload;
10442+
constant_key = ip.indexToKey(payload);
10443+
continue :constant_key constant_key;
10444+
},
10445+
}
1044210446
}
1044310447
},
1044410448
.enum_tag => |enum_tag| continue :constant_key .{ .int = ip.indexToKey(enum_tag.int).int },
@@ -10975,7 +10979,17 @@ fn hasRepeatedByteRepr(isel: *Select, constant: Constant) error{OutOfMemory}!?u8
1097510979
fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMemory}!bool {
1097610980
const zcu = isel.pt.zcu;
1097710981
const ip = &zcu.intern_pool;
10978-
switch (ip.indexToKey(constant.toIntern())) {
10982+
if (try isel.writeKeyToMemory(ip.indexToKey(constant.toIntern()), buffer)) return true;
10983+
constant.writeToMemory(isel.pt, buffer) catch |err| switch (err) {
10984+
error.OutOfMemory => return error.OutOfMemory,
10985+
error.ReinterpretDeclRef, error.Unimplemented, error.IllDefinedMemoryLayout => return false,
10986+
};
10987+
return true;
10988+
}
10989+
fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) error{OutOfMemory}!bool {
10990+
const zcu = isel.pt.zcu;
10991+
const ip = &zcu.intern_pool;
10992+
switch (constant_key) {
1097910993
.int_type,
1098010994
.ptr_type,
1098110995
.array_type,
@@ -10997,6 +11011,37 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1099711011
.empty_enum_value,
1099811012
.memoized_call,
1099911013
=> unreachable, // not a runtime value
11014+
.err => |err| {
11015+
const error_int = ip.getErrorValueIfExists(err.name).?;
11016+
switch (buffer.len) {
11017+
else => unreachable,
11018+
inline 1...4 => |size| std.mem.writeInt(
11019+
@Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 * size } }),
11020+
buffer[0..size],
11021+
@intCast(error_int),
11022+
isel.target.cpu.arch.endian(),
11023+
),
11024+
}
11025+
},
11026+
.error_union => |error_union| {
11027+
const error_union_type = ip.indexToKey(error_union.ty).error_union_type;
11028+
const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
11029+
const payload_ty: ZigType = .fromInterned(error_union_type.payload_type);
11030+
const error_set = buffer[@intCast(codegen.errUnionErrorOffset(payload_ty, zcu))..][0..@intCast(error_set_ty.abiSize(zcu))];
11031+
switch (error_union.val) {
11032+
.err_name => |err_name| if (!try isel.writeKeyToMemory(.{ .err = .{
11033+
.ty = error_set_ty.toIntern(),
11034+
.name = err_name,
11035+
} }, error_set)) return false,
11036+
.payload => |payload| {
11037+
if (!try isel.writeToMemory(
11038+
.fromInterned(payload),
11039+
buffer[@intCast(codegen.errUnionPayloadOffset(payload_ty, zcu))..][0..@intCast(payload_ty.abiSize(zcu))],
11040+
)) return false;
11041+
@memset(error_set, 0);
11042+
},
11043+
}
11044+
},
1100011045
.opt => |opt| {
1100111046
const child_size: usize = @intCast(ZigType.fromInterned(ip.indexToKey(opt.ty).opt_type).abiSize(zcu));
1100211047
switch (opt.val) {
@@ -11008,7 +11053,6 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1100811053
if (!ZigType.fromInterned(opt.ty).optionalReprIsPayload(zcu)) buffer[child_size] = @intFromBool(true);
1100911054
},
1101011055
}
11011-
return true;
1101211056
},
1101311057
.aggregate => |aggregate| switch (ip.indexToKey(aggregate.ty)) {
1101411058
else => unreachable,
@@ -11027,9 +11071,8 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1102711071
elem_offset += elem_size;
1102811072
},
1102911073
}
11030-
return true;
1103111074
},
11032-
.vector_type => {},
11075+
.vector_type => return false,
1103311076
.struct_type => {
1103411077
const loaded_struct = ip.loadStructType(aggregate.ty);
1103511078
switch (loaded_struct.layout) {
@@ -11052,9 +11095,8 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1105211095
}), buffer[@intCast(field_offset)..][0..@intCast(field_size)])) return false;
1105311096
field_offset += field_size;
1105411097
}
11055-
return true;
1105611098
},
11057-
.@"extern", .@"packed" => {},
11099+
.@"extern", .@"packed" => return false,
1105811100
}
1105911101
},
1106011102
.tuple_type => |tuple_type| {
@@ -11071,15 +11113,10 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1107111113
}), buffer[@intCast(field_offset)..][0..@intCast(field_size)])) return false;
1107211114
field_offset += field_size;
1107311115
}
11074-
return true;
1107511116
},
1107611117
},
11077-
else => {},
11118+
else => return false,
1107811119
}
11079-
constant.writeToMemory(isel.pt, buffer) catch |err| switch (err) {
11080-
error.OutOfMemory => return error.OutOfMemory,
11081-
error.ReinterpretDeclRef, error.Unimplemented, error.IllDefinedMemoryLayout => return false,
11082-
};
1108311120
return true;
1108411121
}
1108511122

test/behavior/enum.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,6 @@ test "enum literal casting to tagged union" {
926926
const Bar = enum { A, B, C, D };
927927

928928
test "enum literal casting to error union with payload enum" {
929-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
930929
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
931930

932931
var bar: error{B}!Bar = undefined;

test/behavior/error.zig

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,11 @@ test "implicit cast to optional to error union to return result loc" {
145145
}
146146

147147
test "fn returning empty error set can be passed as fn returning any error" {
148-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
149-
150148
entry();
151149
comptime entry();
152150
}
153151

154152
test "fn returning empty error set can be passed as fn returning any error - pointer" {
155-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
156153
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
157154

158155
entryPtr();
@@ -404,7 +401,6 @@ fn intLiteral(str: []const u8) !?i64 {
404401
}
405402

406403
test "nested error union function call in optional unwrap" {
407-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
408404
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
409405
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
410406

@@ -482,7 +478,6 @@ test "optional error set is the same size as error set" {
482478
}
483479

484480
test "nested catch" {
485-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
486481
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
487482

488483
const S = struct {
@@ -698,7 +693,6 @@ test "coerce error set to the current inferred error set" {
698693
}
699694

700695
test "error union payload is properly aligned" {
701-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
702696
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
703697
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
704698
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -757,7 +751,6 @@ test "simple else prong allowed even when all errors handled" {
757751
}
758752

759753
test "pointer to error union payload" {
760-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
761754
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
762755
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
763756
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -845,7 +838,6 @@ test "alignment of wrapping an error union payload" {
845838
}
846839

847840
test "compare error union and error set" {
848-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
849841
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
850842

851843
var a: anyerror = error.Foo;
@@ -1034,8 +1026,6 @@ test "errorCast to adhoc inferred error set" {
10341026
}
10351027

10361028
test "@errorCast from error set to error union" {
1037-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1038-
10391029
const S = struct {
10401030
fn doTheTest(set: error{ A, B }) error{A}!i32 {
10411031
return @errorCast(set);
@@ -1046,8 +1036,6 @@ test "@errorCast from error set to error union" {
10461036
}
10471037

10481038
test "@errorCast from error union to error union" {
1049-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1050-
10511039
const S = struct {
10521040
fn doTheTest(set: error{ A, B }!i32) error{A}!i32 {
10531041
return @errorCast(set);

test/behavior/while.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ test "while with optional as condition with else" {
174174
}
175175

176176
test "while with error union condition" {
177-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
178177
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
179178
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
180179
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -306,7 +305,6 @@ test "while optional 2 break statements and an else" {
306305
}
307306

308307
test "while error 2 break statements and an else" {
309-
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
310308
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
311309
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
312310

0 commit comments

Comments
 (0)