From c711c788f0a840f45d0d7423efe2f946b47caafb Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 24 May 2022 15:10:18 -0700 Subject: 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). --- src/codegen.zig | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index 86f2613b5f..fbe462959e 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -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; + } } -- cgit v1.2.3