diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index c6ef332403fd6..0ae720e8b7ce8 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1406,6 +1406,99 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) { } } +static void WriteAPFloatInternal(raw_ostream &Out, const APFloat &APF) { + if (&APF.getSemantics() == &APFloat::IEEEsingle() || + &APF.getSemantics() == &APFloat::IEEEdouble()) { + // We would like to output the FP constant value in exponential notation, + // but we cannot do this if doing so will lose precision. Check here to + // make sure that we only output it in exponential format if we can parse + // the value back and get the same value. + // + bool ignored; + bool isDouble = &APF.getSemantics() == &APFloat::IEEEdouble(); + bool isInf = APF.isInfinity(); + bool isNaN = APF.isNaN(); + + if (!isInf && !isNaN) { + double Val = APF.convertToDouble(); + SmallString<128> StrVal; + APF.toString(StrVal, 6, 0, false); + // Check to make sure that the stringized number is not some string like + // "Inf" or NaN, that atof will accept, but the lexer will not. Check + // that the string matches the "[-+]?[0-9]" regex. + // + assert((isDigit(StrVal[0]) || + ((StrVal[0] == '-' || StrVal[0] == '+') && isDigit(StrVal[1]))) && + "[-+]?[0-9] regex does not match!"); + // Reparse stringized version! + if (APFloat(APFloat::IEEEdouble(), StrVal).convertToDouble() == Val) { + Out << StrVal; + return; + } + } + + // Otherwise we could not reparse it to exactly the same value, so we must + // output the string in hexadecimal format! Note that loading and storing + // floating point types changes the bits of NaNs on some hosts, notably + // x86, so we must not use these types. + static_assert(sizeof(double) == sizeof(uint64_t), + "assuming that double is 64 bits!"); + APFloat apf = APF; + + // Floats are represented in ASCII IR as double, convert. + // FIXME: We should allow 32-bit hex float and remove this. + if (!isDouble) { + // A signaling NaN is quieted on conversion, so we need to recreate the + // expected value after convert (quiet bit of the payload is clear). + bool IsSNAN = apf.isSignaling(); + apf.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, + &ignored); + if (IsSNAN) { + APInt Payload = apf.bitcastToAPInt(); + apf = + APFloat::getSNaN(APFloat::IEEEdouble(), apf.isNegative(), &Payload); + } + } + + Out << format_hex(apf.bitcastToAPInt().getZExtValue(), 0, /*Upper=*/true); + return; + } + + // Either half, bfloat or some form of long double. + // These appear as a magic letter identifying the type, then a + // fixed number of hex digits. + Out << "0x"; + APInt API = APF.bitcastToAPInt(); + if (&APF.getSemantics() == &APFloat::x87DoubleExtended()) { + Out << 'K'; + Out << format_hex_no_prefix(API.getHiBits(16).getZExtValue(), 4, + /*Upper=*/true); + Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16, + /*Upper=*/true); + } else if (&APF.getSemantics() == &APFloat::IEEEquad()) { + Out << 'L'; + Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16, + /*Upper=*/true); + Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16, + /*Upper=*/true); + } else if (&APF.getSemantics() == &APFloat::PPCDoubleDouble()) { + Out << 'M'; + Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16, + /*Upper=*/true); + Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16, + /*Upper=*/true); + } else if (&APF.getSemantics() == &APFloat::IEEEhalf()) { + Out << 'H'; + Out << format_hex_no_prefix(API.getZExtValue(), 4, + /*Upper=*/true); + } else if (&APF.getSemantics() == &APFloat::BFloat()) { + Out << 'R'; + Out << format_hex_no_prefix(API.getZExtValue(), 4, + /*Upper=*/true); + } else + llvm_unreachable("Unsupported floating point type"); +} + static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, AsmWriterContext &WriterCtx) { if (const ConstantInt *CI = dyn_cast(CV)) { @@ -1418,94 +1511,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } if (const ConstantFP *CFP = dyn_cast(CV)) { - const APFloat &APF = CFP->getValueAPF(); - if (&APF.getSemantics() == &APFloat::IEEEsingle() || - &APF.getSemantics() == &APFloat::IEEEdouble()) { - // We would like to output the FP constant value in exponential notation, - // but we cannot do this if doing so will lose precision. Check here to - // make sure that we only output it in exponential format if we can parse - // the value back and get the same value. - // - bool ignored; - bool isDouble = &APF.getSemantics() == &APFloat::IEEEdouble(); - bool isInf = APF.isInfinity(); - bool isNaN = APF.isNaN(); - if (!isInf && !isNaN) { - double Val = APF.convertToDouble(); - SmallString<128> StrVal; - APF.toString(StrVal, 6, 0, false); - // Check to make sure that the stringized number is not some string like - // "Inf" or NaN, that atof will accept, but the lexer will not. Check - // that the string matches the "[-+]?[0-9]" regex. - // - assert((isDigit(StrVal[0]) || ((StrVal[0] == '-' || StrVal[0] == '+') && - isDigit(StrVal[1]))) && - "[-+]?[0-9] regex does not match!"); - // Reparse stringized version! - if (APFloat(APFloat::IEEEdouble(), StrVal).convertToDouble() == Val) { - Out << StrVal; - return; - } - } - // Otherwise we could not reparse it to exactly the same value, so we must - // output the string in hexadecimal format! Note that loading and storing - // floating point types changes the bits of NaNs on some hosts, notably - // x86, so we must not use these types. - static_assert(sizeof(double) == sizeof(uint64_t), - "assuming that double is 64 bits!"); - APFloat apf = APF; - // Floats are represented in ASCII IR as double, convert. - // FIXME: We should allow 32-bit hex float and remove this. - if (!isDouble) { - // A signaling NaN is quieted on conversion, so we need to recreate the - // expected value after convert (quiet bit of the payload is clear). - bool IsSNAN = apf.isSignaling(); - apf.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, - &ignored); - if (IsSNAN) { - APInt Payload = apf.bitcastToAPInt(); - apf = APFloat::getSNaN(APFloat::IEEEdouble(), apf.isNegative(), - &Payload); - } - } - Out << format_hex(apf.bitcastToAPInt().getZExtValue(), 0, /*Upper=*/true); - return; - } - - // Either half, bfloat or some form of long double. - // These appear as a magic letter identifying the type, then a - // fixed number of hex digits. - Out << "0x"; - APInt API = APF.bitcastToAPInt(); - if (&APF.getSemantics() == &APFloat::x87DoubleExtended()) { - Out << 'K'; - Out << format_hex_no_prefix(API.getHiBits(16).getZExtValue(), 4, - /*Upper=*/true); - Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16, - /*Upper=*/true); - return; - } else if (&APF.getSemantics() == &APFloat::IEEEquad()) { - Out << 'L'; - Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16, - /*Upper=*/true); - Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16, - /*Upper=*/true); - } else if (&APF.getSemantics() == &APFloat::PPCDoubleDouble()) { - Out << 'M'; - Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16, - /*Upper=*/true); - Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16, - /*Upper=*/true); - } else if (&APF.getSemantics() == &APFloat::IEEEhalf()) { - Out << 'H'; - Out << format_hex_no_prefix(API.getZExtValue(), 4, - /*Upper=*/true); - } else if (&APF.getSemantics() == &APFloat::BFloat()) { - Out << 'R'; - Out << format_hex_no_prefix(API.getZExtValue(), 4, - /*Upper=*/true); - } else - llvm_unreachable("Unsupported floating point type"); + WriteAPFloatInternal(Out, CFP->getValueAPF()); return; }