| ... | ... | @@ -4106,12 +4106,47 @@ static LLVMValueRef ir_render_binary_not(CodeGen *g, Stage1Air *executable, |
| 4106 | 4106 | return LLVMBuildNot(g->builder, operand, ""); |
| 4107 | 4107 | } |
| 4108 | 4108 | |
| 4109 | static LLVMValueRef ir_gen_soft_f80_neg(CodeGen *g, ZigType *op_type, LLVMValueRef operand) { |
| 4110 | uint32_t vector_len = op_type->id == ZigTypeIdVector ? op_type->data.vector.len : 0; |
| 4111 | |
| 4112 | uint64_t buf[2] = {0, 0}; |
| 4113 | if (g->is_big_endian != native_is_big_endian) { |
| 4114 | buf[1] = 0x8000000000000000; |
| 4115 | } else { |
| 4116 | buf[1] = 0x8000; |
| 4117 | } |
| 4118 | LLVMValueRef sign_mask = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf); |
| 4119 | |
| 4120 | LLVMValueRef result; |
| 4121 | if (vector_len == 0) { |
| 4122 | result = LLVMBuildXor(g->builder, operand, sign_mask, ""); |
| 4123 | } else { |
| 4124 | result = build_alloca(g, op_type, "", 0); |
| 4125 | } |
| 4126 | |
| 4127 | LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; |
| 4128 | for (uint32_t i = 0; i < vector_len; i++) { |
| 4129 | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); |
| 4130 | LLVMValueRef xor_operand = LLVMBuildExtractElement(g->builder, operand, index_value, ""); |
| 4131 | LLVMValueRef xor_result = LLVMBuildXor(g->builder, xor_operand, sign_mask, ""); |
| 4132 | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), |
| 4133 | xor_result, index_value, ""); |
| 4134 | } |
| 4135 | if (vector_len != 0) { |
| 4136 | result = LLVMBuildLoad(g->builder, result, ""); |
| 4137 | } |
| 4138 | return result; |
| 4139 | } |
| 4140 | |
| 4109 | 4141 | static LLVMValueRef ir_gen_negation(CodeGen *g, Stage1AirInst *inst, Stage1AirInst *operand, bool wrapping) { |
| 4110 | 4142 | LLVMValueRef llvm_operand = ir_llvm_value(g, operand); |
| 4111 | 4143 | ZigType *operand_type = operand->value->type; |
| 4112 | 4144 | ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? |
| 4113 | 4145 | operand_type->data.vector.elem_type : operand_type; |
| 4114 | 4146 | |
| 4147 | if (scalar_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) |
| 4148 | return ir_gen_soft_f80_neg(g, operand_type, llvm_operand); |
| 4149 | |
| 4115 | 4150 | if (scalar_type->id == ZigTypeIdFloat) { |
| 4116 | 4151 | ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, inst)); |
| 4117 | 4152 | return LLVMBuildFNeg(g->builder, llvm_operand, ""); |