aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2020-01-09 11:56:45 +0100
committerLemonBoy <thatlemon@gmail.com>2020-01-09 11:56:45 +0100
commitc51b79c56e32594e4fb119fc760ae38b69fb9bbb (patch)
treecf906791fd6f2df1240fade35b8c9213a3012e01 /src/ir.cpp
parent7ea7842ed020d5b984d14b824663891aae7549bc (diff)
downloadzig-c51b79c56e32594e4fb119fc760ae38b69fb9bbb.tar.gz
zig-c51b79c56e32594e4fb119fc760ae38b69fb9bbb.zip
Correct alignment calculation for runtime addends
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp34
1 files changed, 17 insertions, 17 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 2a581e0c03..8b5168e477 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -15776,6 +15776,10 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
return ir_const_undef(ira, &instruction->base, op1->value->type);
}
+ ZigType *elem_type = op1->value->type->data.pointer.child_type;
+ if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
+ return ira->codegen->invalid_instruction;
+
// NOTE: this variable is meaningful iff op2_val is not null!
uint64_t byte_offset;
if (op2_val != nullptr) {
@@ -15783,9 +15787,6 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
return ira->codegen->invalid_instruction;
- ZigType *elem_type = op1->value->type->data.pointer.child_type;
- if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
- return ira->codegen->invalid_instruction;
byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
}
@@ -15795,24 +15796,23 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
}
ZigType *result_type = op1->value->type;
- // The resulting pointer may not be aligned anymore
- if (op2_val != nullptr) {
+ // Calculate the new alignment of the pointer
+ {
uint32_t align_bytes;
if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes)))
return ira->codegen->invalid_instruction;
- 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);
+ // If the addend is not a comptime-known value we can still count on
+ // it being a multiple of the type size
+ uint32_t addend = op2_val ? byte_offset : type_size(ira->codegen, elem_type);
+
+ // 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(addend | align_bytes);
+ // Rough guard to prevent overflows
+ assert(new_align);
+ result_type = adjust_ptr_align(ira->codegen, result_type, new_align);
}
if (op2_val != nullptr && op1_val != nullptr &&