Commit 7ea7842ed0

LemonBoy <thatlemon@gmail.com>
2020-01-08 21:02:05
Fix calculation of new alignment factor
1 parent 7fe13f4
Changed files (2)
src
test
stage1
behavior
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);
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;
-
-    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);
+    {
+        var ptr: [*]align(8) u32 = undefined;
+        var x: usize = 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);
+    }
 }