authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-01-09 11:56:45+01:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-01-09 11:56:45+01:00
logc51b79c56e32594e4fb119fc760ae38b69fb9bbb
treecf906791fd6f2df1240fade35b8c9213a3012e01
parent7ea7842ed020d5b984d14b824663891aae7549bc

Correct alignment calculation for runtime addends


2 files changed, 25 insertions(+), 18 deletions(-)

src/ir.cpp+17-17
...@@ -15776,6 +15776,10 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -15776,6 +15776,10 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
15776 return ir_const_undef(ira, &instruction->base, op1->value->type);15776 return ir_const_undef(ira, &instruction->base, op1->value->type);
15777 }15777 }
1577815778
15779 ZigType *elem_type = op1->value->type->data.pointer.child_type;
15780 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
15781 return ira->codegen->invalid_instruction;
15782
15779 // NOTE: this variable is meaningful iff op2_val is not null!15783 // NOTE: this variable is meaningful iff op2_val is not null!
15780 uint64_t byte_offset;15784 uint64_t byte_offset;
15781 if (op2_val != nullptr) {15785 if (op2_val != nullptr) {
...@@ -15783,9 +15787,6 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -15783,9 +15787,6 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
15783 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))15787 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
15784 return ira->codegen->invalid_instruction;15788 return ira->codegen->invalid_instruction;
1578515789
15786 ZigType *elem_type = op1->value->type->data.pointer.child_type;
15787 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
15788 return ira->codegen->invalid_instruction;
15789 byte_offset = type_size(ira->codegen, elem_type) * elem_offset;15790 byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
15790 }15791 }
1579115792
...@@ -15795,24 +15796,23 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -15795,24 +15796,23 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
15795 }15796 }
1579615797
15797 ZigType *result_type = op1->value->type;15798 ZigType *result_type = op1->value->type;
15798 // The resulting pointer may not be aligned anymore15799 // Calculate the new alignment of the pointer
15799 if (op2_val != nullptr) {15800 {
15800 uint32_t align_bytes;15801 uint32_t align_bytes;
15801 if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes)))15802 if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes)))
15802 return ira->codegen->invalid_instruction;15803 return ira->codegen->invalid_instruction;
1580315804
15804 if (byte_offset & (align_bytes - 1)) {15805 // If the addend is not a comptime-known value we can still count on
15805 // The resulting pointer is aligned to the lcd between the15806 // it being a multiple of the type size
15806 // offset (an arbitrary number) and the alignment factor (always15807 uint32_t addend = op2_val ? byte_offset : type_size(ira->codegen, elem_type);
15807 // a power of two, non zero)15808
15808 uint32_t new_align = 1 << ctzll(byte_offset | align_bytes);15809 // The resulting pointer is aligned to the lcd between the
15809 // Rough guard to prevent overflows15810 // offset (an arbitrary number) and the alignment factor (always
15810 assert(new_align);15811 // a power of two, non zero)
15811 result_type = adjust_ptr_align(ira->codegen, result_type, new_align);15812 uint32_t new_align = 1 << ctzll(addend | align_bytes);
15812 }15813 // Rough guard to prevent overflows
15813 } else {15814 assert(new_align);
15814 // The addend is not a comptime-known value15815 result_type = adjust_ptr_align(ira->codegen, result_type, new_align);
15815 result_type = adjust_ptr_align(ira->codegen, result_type, 1);
15816 }15816 }
1581715817
15818 if (op2_val != nullptr && op1_val != nullptr &&15818 if (op2_val != nullptr && op1_val != nullptr &&
test/stage1/behavior/pointers.zig+8-1
...@@ -302,12 +302,19 @@ test "pointer arithmetic affects the alignment" {...@@ -302,12 +302,19 @@ test "pointer arithmetic affects the alignment" {
302 const ptr3 = ptr + 0; // no-op302 const ptr3 = ptr + 0; // no-op
303 expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);303 expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
304 const ptr4 = ptr + x; // runtime-known addend304 const ptr4 = ptr + x; // runtime-known addend
305 expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 1);305 expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
306 }306 }
307 {307 {
308 var ptr: [*]align(8) [3]u8 = undefined;308 var ptr: [*]align(8) [3]u8 = undefined;
309 var x: usize = 1;
309310
310 const ptr1 = ptr + 17; // 3 * 17 = 51311 const ptr1 = ptr + 17; // 3 * 17 = 51
311 expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1);312 expect(@typeInfo(@TypeOf(ptr1)).Pointer.alignment == 1);
313 const ptr2 = ptr + x; // runtime-known addend
314 expect(@typeInfo(@TypeOf(ptr2)).Pointer.alignment == 1);
315 const ptr3 = ptr + 8; // 3 * 8 = 24 -> lcd(8,24) = 8
316 expect(@typeInfo(@TypeOf(ptr3)).Pointer.alignment == 8);
317 const ptr4 = ptr + 4; // 3 * 4 = 12 -> lcd(8,12) = 4
318 expect(@typeInfo(@TypeOf(ptr4)).Pointer.alignment == 4);
312 }319 }
313}320}