stage2: fixes for error unions, optionals, errors

* `?E` where E is an error set with only one field now lowers the same
   as `bool`.
 * Fix implementation of errUnionErrOffset and errUnionPayloadOffset to
   properly compute the offset of each field. Also name them the same
   as the corresponding LLVM functions and have the same function
   signature, to avoid confusion. This fixes a bug where wasm was
   passing the error union type instead of the payload type.
 * Fix C backend handling of optionals with zero-bit payload types.
 * C backend: separate out airOptionalPayload and airOptionalPayloadPtr
   which reduces branching and cleans up control flow.
 * Make Type.isNoReturn return true for error sets with no fields.
 * Make `?error{}` have only one possible value (null).
This commit is contained in:
Andrew Kelley
2022-05-24 15:10:18 -07:00
parent c847a462ae
commit c711c788f0
9 changed files with 192 additions and 77 deletions

View File

@@ -891,18 +891,22 @@ fn lowerDeclRef(
return Result{ .appended = {} };
}
pub fn errUnionPayloadOffset(ty: Type, target: std.Target) u64 {
const payload_ty = ty.errorUnionPayload();
return if (Type.anyerror.abiAlignment(target) >= payload_ty.abiAlignment(target))
Type.anyerror.abiSize(target)
else
0;
pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {
const payload_align = payload_ty.abiAlignment(target);
const error_align = Type.anyerror.abiAlignment(target);
if (payload_align >= error_align) {
return 0;
} else {
return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(target), payload_align);
}
}
pub fn errUnionErrOffset(ty: Type, target: std.Target) u64 {
const payload_ty = ty.errorUnionPayload();
return if (Type.anyerror.abiAlignment(target) >= payload_ty.abiAlignment(target))
0
else
payload_ty.abiSize(target);
pub fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u64 {
const payload_align = payload_ty.abiAlignment(target);
const error_align = Type.anyerror.abiAlignment(target);
if (payload_align >= error_align) {
return mem.alignForwardGeneric(u64, payload_ty.abiSize(target), error_align);
} else {
return 0;
}
}