diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 2c63d85089..fffa834d1c 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -4139,13 +4139,9 @@ static LLVMValueRef ir_render_binary_not(CodeGen *g, Stage1Air *executable, static LLVMValueRef ir_gen_soft_f80_neg(CodeGen *g, ZigType *op_type, LLVMValueRef operand) { uint32_t vector_len = op_type->id == ZigTypeIdVector ? op_type->data.vector.len : 0; - uint64_t buf[2] = {0, 0}; - if (g->is_big_endian != native_is_big_endian) { - buf[1] = 0x8000000000000000; - } else { - buf[1] = 0x8000; - } - LLVMValueRef sign_mask = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf); + LLVMTypeRef llvm_i80 = LLVMIntType(80); + LLVMValueRef sign_mask = LLVMConstInt(llvm_i80, 1, false); + sign_mask = LLVMConstShl(sign_mask, LLVMConstInt(llvm_i80, 79, false)); LLVMValueRef result; if (vector_len == 0) { diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 3c9121d019..22c576e5f5 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -448,3 +448,21 @@ fn testTrunc() !void { try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon)); } } + +test "negation" { + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.os.tag == .freebsd) return error.SkipZigTest; + + const S = struct { + fn doTheTest() !void { + inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { + var a: T = 1; + a = -a; + try expect(a == -1); + } + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +}