diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d872057beb..d1c68b430c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -6188,7 +6188,9 @@ pub const FuncGen = struct { } const llvm_optional_ty = try self.dg.lowerType(optional_ty); if (isByRef(optional_ty)) { + const target = self.dg.module.getTarget(); const optional_ptr = self.buildAlloca(llvm_optional_ty); + optional_ptr.setAlignment(optional_ty.abiAlignment(target)); const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, @@ -6208,20 +6210,21 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const inst_ty = self.air.typeOfIndex(inst); + const err_un_ty = self.air.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); const payload_ty = self.air.typeOf(ty_op.operand); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { return operand; } const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull(); - const err_un_llvm_ty = try self.dg.lowerType(inst_ty); + const err_un_llvm_ty = try self.dg.lowerType(err_un_ty); const target = self.dg.module.getTarget(); const payload_offset = errUnionPayloadOffset(payload_ty, target); const error_offset = errUnionErrorOffset(payload_ty, target); - if (isByRef(inst_ty)) { + if (isByRef(err_un_ty)) { const result_ptr = self.buildAlloca(err_un_llvm_ty); + result_ptr.setAlignment(err_un_ty.abiAlignment(target)); const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); const store_inst = self.builder.buildStore(ok_err_code, err_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); @@ -6256,6 +6259,7 @@ pub const FuncGen = struct { const error_offset = errUnionErrorOffset(payload_ty, target); if (isByRef(err_un_ty)) { const result_ptr = self.buildAlloca(err_un_llvm_ty); + result_ptr.setAlignment(err_un_ty.abiAlignment(target)); const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); const store_inst = self.builder.buildStore(operand, err_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); diff --git a/test/behavior/error.zig b/test/behavior/error.zig index b355c85819..684b01a797 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -796,3 +796,19 @@ test "error union of noreturn used with catch" { const err = NoReturn.testCatch(); try expect(err == error.OtherFailure); } + +test "alignment of wrapping an error union payload" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + + const S = struct { + const I = extern struct { x: i128 }; + + fn foo() anyerror!I { + var i: I = .{ .x = 1234 }; + return i; + } + }; + try expect((S.foo() catch unreachable).x == 1234); +} diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index 28261daf1f..eb693147e6 100644 --- a/test/behavior/optional.zig +++ b/test/behavior/optional.zig @@ -412,3 +412,19 @@ test "orelse on C pointer" { const d = foo orelse @compileError("bad"); try expectEqual([*c]const u8, @TypeOf(d)); } + +test "alignment of wrapping an optional payload" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + + const S = struct { + const I = extern struct { x: i128 }; + + fn foo() ?I { + var i: I = .{ .x = 1234 }; + return i; + } + }; + try expect(S.foo().?.x == 1234); +}