From e134e6c994d6ecd76dc6ae1a24b8de29c4147eab Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 20 Dec 2019 10:48:03 +0100 Subject: Pointer arithmetic affects the alignment factor Closes #1528 --- src/ir.cpp | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index e841da35d0..f7e7aa8902 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15776,19 +15776,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp return ir_const_undef(ira, &instruction->base, op1->value->type); } + // NOTE: this variable is meaningful iff op2_val is not null! + uint64_t byte_offset; + if (op2_val != nullptr) { + uint64_t elem_offset; + 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; + } + + // Fast path for cases where the RHS is zero + if (op2_val != nullptr && byte_offset == 0) { + return op1; + } + + ZigType *result_type = op1->value->type; + // The resulting pointer may not be aligned anymore + if (op2_val != nullptr) { + uint32_t align_bytes; + 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); + } else { + // The addend is not a comptime-known value + result_type = adjust_ptr_align(ira->codegen, result_type, 1); + } + if (op2_val != nullptr && op1_val != nullptr && (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || op1->value->data.x_ptr.special == ConstPtrSpecialNull)) { uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ? 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr; - uint64_t elem_offset; - if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) - return ira->codegen->invalid_instruction; - ZigType *elem_type = op1_val->type->data.pointer.child_type; - if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; - uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset; uint64_t new_addr; if (op_id == IrBinOpAdd) { new_addr = start_addr + byte_offset; @@ -15797,7 +15822,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp } else { zig_unreachable(); } - IrInstruction *result = ir_const(ira, &instruction->base, op1_val->type); + IrInstruction *result = ir_const(ira, &instruction->base, result_type); result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr; @@ -15806,7 +15831,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, instruction->base.source_node, op_id, op1, casted_op2, true); - result->value->type = op1->value->type; + result->value->type = result_type; return result; } -- cgit v1.2.3