| ... | @@ -15776,19 +15776,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -15776,19 +15776,44 @@ 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 | } |
| 15778 | | 15778 | |
| | 15779 | // NOTE: this variable is meaningful iff op2_val is not null! |
| | 15780 | uint64_t byte_offset; |
| | 15781 | if (op2_val != nullptr) { |
| | 15782 | uint64_t elem_offset; |
| | 15783 | if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) |
| | 15784 | return ira->codegen->invalid_instruction; |
| | 15785 | |
| | 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 | } |
| | 15791 | |
| | 15792 | // Fast path for cases where the RHS is zero |
| | 15793 | if (op2_val != nullptr && byte_offset == 0) { |
| | 15794 | return op1; |
| | 15795 | } |
| | 15796 | |
| | 15797 | ZigType *result_type = op1->value->type; |
| | 15798 | // The resulting pointer may not be aligned anymore |
| | 15799 | if (op2_val != nullptr) { |
| | 15800 | uint32_t align_bytes; |
| | 15801 | if ((err = resolve_ptr_align(ira, op1->value->type, &align_bytes))) |
| | 15802 | return ira->codegen->invalid_instruction; |
| | 15803 | |
| | 15804 | if (byte_offset != 0 && byte_offset % align_bytes != 0) |
| | 15805 | result_type = adjust_ptr_align(ira->codegen, result_type, 1); |
| | 15806 | } else { |
| | 15807 | // The addend is not a comptime-known value |
| | 15808 | result_type = adjust_ptr_align(ira->codegen, result_type, 1); |
| | 15809 | } |
| | 15810 | |
| 15779 | if (op2_val != nullptr && op1_val != nullptr && | 15811 | if (op2_val != nullptr && op1_val != nullptr && |
| 15780 | (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || | 15812 | (op1->value->data.x_ptr.special == ConstPtrSpecialHardCodedAddr || |
| 15781 | op1->value->data.x_ptr.special == ConstPtrSpecialNull)) | 15813 | op1->value->data.x_ptr.special == ConstPtrSpecialNull)) |
| 15782 | { | 15814 | { |
| 15783 | uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ? | 15815 | uint64_t start_addr = (op1_val->data.x_ptr.special == ConstPtrSpecialNull) ? |
| 15784 | 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr; | 15816 | 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr; |
| 15785 | uint64_t elem_offset; | | |
| 15786 | if (!ir_resolve_usize(ira, casted_op2, &elem_offset)) | | |
| 15787 | return ira->codegen->invalid_instruction; | | |
| 15788 | ZigType *elem_type = op1_val->type->data.pointer.child_type; | | |
| 15789 | if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) | | |
| 15790 | return ira->codegen->invalid_instruction; | | |
| 15791 | uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset; | | |
| 15792 | uint64_t new_addr; | 15817 | uint64_t new_addr; |
| 15793 | if (op_id == IrBinOpAdd) { | 15818 | if (op_id == IrBinOpAdd) { |
| 15794 | new_addr = start_addr + byte_offset; | 15819 | new_addr = start_addr + byte_offset; |
| ... | @@ -15797,7 +15822,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -15797,7 +15822,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 15797 | } else { | 15822 | } else { |
| 15798 | zig_unreachable(); | 15823 | zig_unreachable(); |
| 15799 | } | 15824 | } |
| 15800 | IrInstruction *result = ir_const(ira, &instruction->base, op1_val->type); | 15825 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); |
| 15801 | result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | 15826 | result->value->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| 15802 | result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; | 15827 | result->value->data.x_ptr.mut = ConstPtrMutRuntimeVar; |
| 15803 | result->value->data.x_ptr.data.hard_coded_addr.addr = new_addr; | 15828 | 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 | ... | @@ -15806,7 +15831,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 15806 | | 15831 | |
| 15807 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, | 15832 | IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope, |
| 15808 | instruction->base.source_node, op_id, op1, casted_op2, true); | 15833 | instruction->base.source_node, op_id, op1, casted_op2, true); |
| 15809 | result->value->type = op1->value->type; | 15834 | result->value->type = result_type; |
| 15810 | return result; | 15835 | return result; |
| 15811 | } | 15836 | } |
| 15812 | | 15837 | |