authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-19 16:30:25+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-22 00:12:37+02:00
loga492a607d5410b1136db3a63fabd01c10827144c
tree03b8a57ab199edd346ae666e890000d80721f5b3
parentd284c00fda45b943f4ed5244ae1cb9e7f90f481f

type: correct condition for eliding pointer alignment canonicalization

Closes #14373

2 files changed, 49 insertions(+), 6 deletions(-)

src/type.zig+34-6
......@@ -3789,6 +3789,39 @@ pub const Type = extern union {
37893789 }
37903790 }
37913791
3792 /// Returns true if the type's layout is already resolved and it is safe
3793 /// to use `abiSize`, `abiAlignment` and `bitSize` on it.
3794 pub fn layoutIsResolved(ty: Type) bool {
3795 switch (ty.zigTypeTag()) {
3796 .Struct => {
3797 if (ty.castTag(.@"struct")) |struct_ty| {
3798 return struct_ty.data.haveLayout();
3799 }
3800 return true;
3801 },
3802 .Union => {
3803 if (ty.cast(Payload.Union)) |union_ty| {
3804 return union_ty.data.haveLayout();
3805 }
3806 return true;
3807 },
3808 .Array => {
3809 if (ty.arrayLenIncludingSentinel() == 0) return true;
3810 return ty.childType().layoutIsResolved();
3811 },
3812 .Optional => {
3813 var buf: Type.Payload.ElemType = undefined;
3814 const payload_ty = ty.optionalChild(&buf);
3815 return payload_ty.layoutIsResolved();
3816 },
3817 .ErrorUnion => {
3818 const payload_ty = ty.errorUnionPayload();
3819 return payload_ty.layoutIsResolved();
3820 },
3821 else => return true,
3822 }
3823 }
3824
37923825 pub fn isSinglePointer(self: Type) bool {
37933826 return switch (self.tag()) {
37943827 .single_const_pointer,
......@@ -6498,12 +6531,7 @@ pub const Type = extern union {
64986531 // pointee type needs to be resolved more, that needs to be done before calling
64996532 // this ptr() function.
65006533 if (d.@"align" != 0) canonicalize: {
6501 if (d.pointee_type.castTag(.@"struct")) |struct_ty| {
6502 if (!struct_ty.data.haveLayout()) break :canonicalize;
6503 }
6504 if (d.pointee_type.cast(Payload.Union)) |union_ty| {
6505 if (!union_ty.data.haveLayout()) break :canonicalize;
6506 }
6534 if (!d.pointee_type.layoutIsResolved()) break :canonicalize;
65076535 if (d.@"align" == d.pointee_type.abiAlignment(target)) {
65086536 d.@"align" = 0;
65096537 }
test/behavior/pointers.zig+15
......@@ -532,3 +532,18 @@ test "pointer alignment and element type include call expression" {
532532 };
533533 try expect(@alignOf(S.P) > 0);
534534}
535
536test "pointer to array has explicit alignment" {
537 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
538
539 const S = struct {
540 const Base = extern struct { a: u8 };
541 const Base2 = extern struct { a: u8 };
542 fn func(ptr: *[4]Base) *align(1) [4]Base2 {
543 return @alignCast(1, @ptrCast(*[4]Base2, ptr));
544 }
545 };
546 var bases = [_]S.Base{.{ .a = 2 }} ** 4;
547 const casted = S.func(&bases);
548 try expect(casted[0].a == 2);
549}