authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-18 21:57:18-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-18 22:11:26-05:00
log52e5c6602550788cab96957d1a177bc7952d7a09
tree53615c2f51c4ac8cec3fdb63941efe24e9b8875a
parent18f05664dcf9c3a307d269dda4f146bafbca19e9

llvm: fix use of invalid alignment

* Initialize `big_align` with 1 as 0 is not a valid alignment. * Add an assert to `alignForwardGeneric` to catch this issue earlier. * Refactor valid alignment checks to call a more descriptive function.

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

lib/std/mem.zig+12-5
...@@ -3291,7 +3291,7 @@ pub fn nativeToBig(comptime T: type, x: T) T {...@@ -3291,7 +3291,7 @@ pub fn nativeToBig(comptime T: type, x: T) T {
3291/// - The delta required to align the pointer is not a multiple of the pointee's3291/// - The delta required to align the pointer is not a multiple of the pointee's
3292/// type.3292/// type.
3293pub fn alignPointerOffset(ptr: anytype, align_to: usize) ?usize {3293pub fn alignPointerOffset(ptr: anytype, align_to: usize) ?usize {
3294 assert(align_to != 0 and @popCount(align_to) == 1);3294 assert(isValidAlign(align_to));
32953295
3296 const T = @TypeOf(ptr);3296 const T = @TypeOf(ptr);
3297 const info = @typeInfo(T);3297 const info = @typeInfo(T);
...@@ -3751,6 +3751,7 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {...@@ -3751,6 +3751,7 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {
3751/// The alignment must be a power of 2 and greater than 0.3751/// The alignment must be a power of 2 and greater than 0.
3752/// Asserts that rounding up the address does not cause integer overflow.3752/// Asserts that rounding up the address does not cause integer overflow.
3753pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T {3753pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T {
3754 assert(isValidAlignGeneric(T, alignment));
3754 return alignBackwardGeneric(T, addr + (alignment - 1), alignment);3755 return alignBackwardGeneric(T, addr + (alignment - 1), alignment);
3755}3756}
37563757
...@@ -3846,7 +3847,7 @@ test "alignForward" {...@@ -3846,7 +3847,7 @@ test "alignForward" {
3846/// Round an address down to the previous (or current) aligned address.3847/// Round an address down to the previous (or current) aligned address.
3847/// Unlike `alignBackward`, `alignment` can be any positive number, not just a power of 2.3848/// Unlike `alignBackward`, `alignment` can be any positive number, not just a power of 2.
3848pub fn alignBackwardAnyAlign(i: usize, alignment: usize) usize {3849pub fn alignBackwardAnyAlign(i: usize, alignment: usize) usize {
3849 if (@popCount(alignment) == 1)3850 if (isValidAlign(alignment))
3850 return alignBackward(i, alignment);3851 return alignBackward(i, alignment);
3851 assert(alignment != 0);3852 assert(alignment != 0);
3852 return i - @mod(i, alignment);3853 return i - @mod(i, alignment);
...@@ -3861,7 +3862,7 @@ pub fn alignBackward(addr: usize, alignment: usize) usize {...@@ -3861,7 +3862,7 @@ pub fn alignBackward(addr: usize, alignment: usize) usize {
3861/// Round an address down to the previous (or current) aligned address.3862/// Round an address down to the previous (or current) aligned address.
3862/// The alignment must be a power of 2 and greater than 0.3863/// The alignment must be a power of 2 and greater than 0.
3863pub fn alignBackwardGeneric(comptime T: type, addr: T, alignment: T) T {3864pub fn alignBackwardGeneric(comptime T: type, addr: T, alignment: T) T {
3864 assert(@popCount(alignment) == 1);3865 assert(isValidAlignGeneric(T, alignment));
3865 // 000010000 // example alignment3866 // 000010000 // example alignment
3866 // 000001111 // subtract 13867 // 000001111 // subtract 1
3867 // 111110000 // binary not3868 // 111110000 // binary not
...@@ -3871,11 +3872,17 @@ pub fn alignBackwardGeneric(comptime T: type, addr: T, alignment: T) T {...@@ -3871,11 +3872,17 @@ pub fn alignBackwardGeneric(comptime T: type, addr: T, alignment: T) T {
3871/// Returns whether `alignment` is a valid alignment, meaning it is3872/// Returns whether `alignment` is a valid alignment, meaning it is
3872/// a positive power of 2.3873/// a positive power of 2.
3873pub fn isValidAlign(alignment: usize) bool {3874pub fn isValidAlign(alignment: usize) bool {
3874 return @popCount(alignment) == 1;3875 return isValidAlignGeneric(usize, alignment);
3876}
3877
3878/// Returns whether `alignment` is a valid alignment, meaning it is
3879/// a positive power of 2.
3880pub fn isValidAlignGeneric(comptime T: type, alignment: T) bool {
3881 return alignment > 0 and std.math.isPowerOfTwo(alignment);
3875}3882}
38763883
3877pub fn isAlignedAnyAlign(i: usize, alignment: usize) bool {3884pub fn isAlignedAnyAlign(i: usize, alignment: usize) bool {
3878 if (@popCount(alignment) == 1)3885 if (isValidAlign(alignment))
3879 return isAligned(i, alignment);3886 return isAligned(i, alignment);
3880 assert(alignment != 0);3887 assert(alignment != 0);
3881 return 0 == @mod(i, alignment);3888 return 0 == @mod(i, alignment);
src/codegen/llvm.zig+1-1
...@@ -2969,7 +2969,7 @@ pub const DeclGen = struct {...@@ -2969,7 +2969,7 @@ pub const DeclGen = struct {
29692969
2970 comptime assert(struct_layout_version == 2);2970 comptime assert(struct_layout_version == 2);
2971 var offset: u64 = 0;2971 var offset: u64 = 0;
2972 var big_align: u32 = 0;2972 var big_align: u32 = 1;
2973 var any_underaligned_fields = false;2973 var any_underaligned_fields = false;
29742974
2975 for (struct_obj.fields.values()) |field| {2975 for (struct_obj.fields.values()) |field| {