diff --git a/src/ir.cpp b/src/ir.cpp index f7e7aa8902..2a581e0c03 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15801,8 +15801,15 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes))) return ira->codegen->invalid_instruction; - if (byte_offset != 0 && byte_offset % align_bytes != 0) - result_type = adjust_ptr_align(ira->codegen, result_type, 1); + if (byte_offset & (align_bytes - 1)) { + // The resulting pointer is aligned to the lcd between the + // offset (an arbitrary number) and the alignment factor (always + // a power of two, non zero) + uint32_t new_align = 1 << ctzll(byte_offset | align_bytes); + // Rough guard to prevent overflows + assert(new_align); + result_type = adjust_ptr_align(ira->codegen, result_type, new_align); + } } else { // The addend is not a comptime-known value result_type = adjust_ptr_align(ira->codegen, result_type, 1); diff --git a/test/stage1/behavior/pointers.zig b/test/stage1/behavior/pointers.zig index 048cdb150f..28b871bd5d 100644 --- a/test/stage1/behavior/pointers.zig +++ b/test/stage1/behavior/pointers.zig @@ -290,17 +290,24 @@ test "pointer to array at fixed address" { } test "pointer arithmetic affects the alignment" { - var arr: [10]u8 align(2) = undefined; - var x: usize = 1; + { + var ptr: [*]align(8) u32 = undefined; + var x: usize = 1; - const ptr = @as([*]u8, &arr); - expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 2); - const ptr1 = ptr + 1; - expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1); - const ptr2 = ptr + 4; - expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 2); - const ptr3 = ptr + 0; - expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 2); - const ptr4 = ptr + x; - expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 1); + expect(@typeInfo(@TypeOf(ptr)).Pointer.alignment == 8); + const ptr1 = ptr + 1; // 1 * 4 = 4 -> lcd(4,8) = 4 + expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 4); + const ptr2 = ptr + 4; // 4 * 4 = 16 -> lcd(16,8) = 8 + expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 8); + const ptr3 = ptr + 0; // no-op + expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8); + const ptr4 = ptr + x; // runtime-known addend + expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 1); + } + { + var ptr: [*]align(8) [3]u8 = undefined; + + const ptr1 = ptr + 17; // 3 * 17 = 51 + expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1); + } }