| ... | @@ -1593,35 +1593,16 @@ static const BuildBinOpFunc unsigned_op[3] = { LLVMBuildNUWAdd, LLVMBuildNUWSub, | ... | @@ -1593,35 +1593,16 @@ static const BuildBinOpFunc unsigned_op[3] = { LLVMBuildNUWAdd, LLVMBuildNUWSub, |
| 1593 | static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul op, | 1593 | static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul op, |
| 1594 | LLVMValueRef val1, LLVMValueRef val2) | 1594 | LLVMValueRef val1, LLVMValueRef val2) |
| 1595 | { | 1595 | { |
| 1596 | LLVMValueRef overflow_bit; | 1596 | LLVMValueRef fn_val = get_int_overflow_fn(g, operand_type, op); |
| 1597 | LLVMValueRef result; | 1597 | LLVMValueRef params[] = { |
| 1598 | | 1598 | val1, |
| | 1599 | val2, |
| | 1600 | }; |
| | 1601 | LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); |
| | 1602 | LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); |
| | 1603 | LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); |
| 1599 | if (operand_type->id == ZigTypeIdVector) { | 1604 | if (operand_type->id == ZigTypeIdVector) { |
| 1600 | ZigType *int_type = operand_type->data.vector.elem_type; | 1605 | overflow_bit = ZigLLVMBuildOrReduce(g->builder, overflow_bit); |
| 1601 | assert(int_type->id == ZigTypeIdInt); | | |
| 1602 | LLVMTypeRef one_more_bit_int = LLVMIntType(int_type->data.integral.bit_count + 1); | | |
| 1603 | LLVMTypeRef one_more_bit_int_vector = LLVMVectorType(one_more_bit_int, operand_type->data.vector.len); | | |
| 1604 | const auto buildExtFn = int_type->data.integral.is_signed ? LLVMBuildSExt : LLVMBuildZExt; | | |
| 1605 | LLVMValueRef extended1 = buildExtFn(g->builder, val1, one_more_bit_int_vector, ""); | | |
| 1606 | LLVMValueRef extended2 = buildExtFn(g->builder, val2, one_more_bit_int_vector, ""); | | |
| 1607 | LLVMValueRef extended_result = wrap_op[op](g->builder, extended1, extended2, ""); | | |
| 1608 | result = LLVMBuildTrunc(g->builder, extended_result, get_llvm_type(g, operand_type), ""); | | |
| 1609 | | | |
| 1610 | LLVMValueRef re_extended_result = buildExtFn(g->builder, result, one_more_bit_int_vector, ""); | | |
| 1611 | LLVMValueRef overflow_vector = LLVMBuildICmp(g->builder, LLVMIntNE, extended_result, re_extended_result, ""); | | |
| 1612 | LLVMTypeRef bitcast_int_type = LLVMIntType(operand_type->data.vector.len); | | |
| 1613 | LLVMValueRef bitcasted_overflow = LLVMBuildBitCast(g->builder, overflow_vector, bitcast_int_type, ""); | | |
| 1614 | LLVMValueRef zero = LLVMConstNull(bitcast_int_type); | | |
| 1615 | overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, bitcasted_overflow, zero, ""); | | |
| 1616 | } else { | | |
| 1617 | LLVMValueRef fn_val = get_int_overflow_fn(g, operand_type, op); | | |
| 1618 | LLVMValueRef params[] = { | | |
| 1619 | val1, | | |
| 1620 | val2, | | |
| 1621 | }; | | |
| 1622 | LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); | | |
| 1623 | result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); | | |
| 1624 | overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); | | |
| 1625 | } | 1606 | } |
| 1626 | | 1607 | |
| 1627 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail"); | 1608 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail"); |