From 1b25cb2416c46a6cebf2a6c52235e9fe46a10d11 Mon Sep 17 00:00:00 2001 From: Dale Johannesen Date: Mon, 23 Mar 2009 21:16:53 +0000 Subject: Fix internal representation of fp80 to be the same as a normal i80 {low64, high16} rather than its own {high64, low16}. A depressing number of places know about this; I think I got them all. Bitcode readers and writers convert back to the old form to avoid breaking compatibility. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67562 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AsmParser/LLLexer.cpp | 35 ++++++++++++++++++++++++++++++++++- lib/AsmParser/LLLexer.h | 1 + lib/Bitcode/Reader/BitcodeReader.cpp | 10 +++++++--- lib/Bitcode/Writer/BitcodeWriter.cpp | 5 +++-- lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 16 ++++++++-------- lib/Support/APFloat.cpp | 14 ++++++-------- lib/Target/CBackend/CBackend.cpp | 5 ++--- lib/VMCore/AsmWriter.cpp | 24 ++++++++++++++++++++++-- 8 files changed, 83 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 5a38e60..95e6c90 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -115,6 +115,37 @@ void LLLexer::HexToIntPair(const char *Buffer, const char *End, Error("constant bigger than 128 bits detected!"); } +/// FP80HexToIntPair - translate an 80 bit FP80 number (20 hexits) into +/// { low64, high16 } as usual for an APInt. +void LLLexer::FP80HexToIntPair(const char *Buffer, const char *End, + uint64_t Pair[2]) { + Pair[1] = 0; + for (int i=0; i<4 && Buffer != End; i++, Buffer++) { + assert(Buffer != End); + Pair[1] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[1] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[1] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[1] += C-'a'+10; + } + Pair[0] = 0; + for (int i=0; i<16; i++, Buffer++) { + Pair[0] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[0] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[0] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[0] += C-'a'+10; + } + if (Buffer != End) + Error("constant bigger than 128 bits detected!"); +} + // UnEscapeLexed - Run through the specified buffer and change \xx codes to the // appropriate character. static void UnEscapeLexed(std::string &Str) { @@ -670,19 +701,21 @@ lltok::Kind LLLexer::Lex0x() { } uint64_t Pair[2]; - HexToIntPair(TokStart+3, CurPtr, Pair); switch (Kind) { default: assert(0 && "Unknown kind!"); case 'K': // F80HexFPConstant - x87 long double in hexadecimal format (10 bytes) + FP80HexToIntPair(TokStart+3, CurPtr, Pair); APFloatVal = APFloat(APInt(80, 2, Pair)); return lltok::APFloat; case 'L': // F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes) + HexToIntPair(TokStart+3, CurPtr, Pair); APFloatVal = APFloat(APInt(128, 2, Pair), true); return lltok::APFloat; case 'M': // PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes) + HexToIntPair(TokStart+3, CurPtr, Pair); APFloatVal = APFloat(APInt(128, 2, Pair)); return lltok::APFloat; } diff --git a/lib/AsmParser/LLLexer.h b/lib/AsmParser/LLLexer.h index adf053c..995aa4e 100644 --- a/lib/AsmParser/LLLexer.h +++ b/lib/AsmParser/LLLexer.h @@ -77,6 +77,7 @@ namespace llvm { uint64_t atoull(const char *Buffer, const char *End); uint64_t HexIntToVal(const char *Buffer, const char *End); void HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); + void FP80HexToIntPair(const char *Buff, const char *End, uint64_t Pair[2]); }; } // end namespace llvm diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 299ce0b..69eadd9 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -801,9 +801,13 @@ bool BitcodeReader::ParseConstants() { V = ConstantFP::get(APFloat(APInt(32, (uint32_t)Record[0]))); else if (CurTy == Type::DoubleTy) V = ConstantFP::get(APFloat(APInt(64, Record[0]))); - else if (CurTy == Type::X86_FP80Ty) - V = ConstantFP::get(APFloat(APInt(80, 2, &Record[0]))); - else if (CurTy == Type::FP128Ty) + else if (CurTy == Type::X86_FP80Ty) { + // Bits are not stored the same way as a normal i80 APInt, compensate. + uint64_t Rearrange[2]; + Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16); + Rearrange[1] = Record[0] >> 48; + V = ConstantFP::get(APFloat(APInt(80, 2, Rearrange))); + } else if (CurTy == Type::FP128Ty) V = ConstantFP::get(APFloat(APInt(128, 2, &Record[0]), true)); else if (CurTy == Type::PPC_FP128Ty) V = ConstantFP::get(APFloat(APInt(128, 2, &Record[0]))); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 1055564..d4d3443 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -559,10 +559,11 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); } else if (Ty == Type::X86_FP80Ty) { // api needed to prevent premature destruction + // bits are not in the same order as a normal i80 APInt, compensate. APInt api = CFP->getValueAPF().bitcastToAPInt(); const uint64_t *p = api.getRawData(); - Record.push_back(p[0]); - Record.push_back((uint16_t)p[1]); + Record.push_back((p[1] << 48) | (p[0] >> 16)); + Record.push_back(p[0] & 0xffffLL); } else if (Ty == Type::FP128Ty || Ty == Type::PPC_FP128Ty) { APInt api = CFP->getValueAPF().bitcastToAPInt(); const uint64_t *p = api.getRawData(); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 2a64524..79d14f7 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1046,10 +1046,13 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored); if (TD->isBigEndian()) { - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48) + O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]) << '\t' << TAI->getCommentString() << " long double most significant halfword of ~" << DoubleVal.convertToDouble() << '\n'; + O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48) + << '\t' << TAI->getCommentString() + << " long double next halfword\n"; O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 32) << '\t' << TAI->getCommentString() << " long double next halfword\n"; @@ -1058,18 +1061,12 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, << " long double next halfword\n"; O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]) << '\t' << TAI->getCommentString() - << " long double next halfword\n"; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]) - << '\t' << TAI->getCommentString() << " long double least significant halfword\n"; } else { - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]) + O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]) << '\t' << TAI->getCommentString() << " long double least significant halfword of ~" << DoubleVal.convertToDouble() << '\n'; - O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0]) - << '\t' << TAI->getCommentString() - << " long double next halfword\n"; O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 16) << '\t' << TAI->getCommentString() << " long double next halfword\n"; @@ -1078,6 +1075,9 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, << " long double next halfword\n"; O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[0] >> 48) << '\t' << TAI->getCommentString() + << " long double next halfword\n"; + O << TAI->getData16bitsDirective(AddrSpace) << uint16_t(p[1]) + << '\t' << TAI->getCommentString() << " long double most significant halfword\n"; } EmitZeros(TD->getTypePaddedSize(Type::X86_FP80Ty) - diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index d7f0d82..2ee6a27 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -2603,10 +2603,9 @@ APFloat::convertF80LongDoubleAPFloatToAPInt() const } uint64_t words[2]; - words[0] = ((uint64_t)(sign & 1) << 63) | - ((myexponent & 0x7fffLL) << 48) | - ((mysignificand >>16) & 0xffffffffffffLL); - words[1] = mysignificand & 0xffff; + words[0] = mysignificand; + words[1] = ((uint64_t)(sign & 1) << 15) | + (myexponent & 0x7fffLL); return APInt(80, 2, words); } @@ -2764,14 +2763,13 @@ APFloat::initFromF80LongDoubleAPInt(const APInt &api) assert(api.getBitWidth()==80); uint64_t i1 = api.getRawData()[0]; uint64_t i2 = api.getRawData()[1]; - uint64_t myexponent = (i1 >> 48) & 0x7fff; - uint64_t mysignificand = ((i1 << 16) & 0xffffffffffff0000ULL) | - (i2 & 0xffff); + uint64_t myexponent = (i2 & 0x7fff); + uint64_t mysignificand = i1; initialize(&APFloat::x87DoubleExtended); assert(partCount()==2); - sign = static_cast(i1>>63); + sign = static_cast(i2>>15); if (myexponent==0 && mysignificand==0) { // exponent, significand meaningless category = fcZero; diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 53c9864..fc99f50 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -2087,9 +2087,8 @@ void CWriter::printFloatingPointConstants(const Constant *C) { APInt api = FPC->getValueAPF().bitcastToAPInt(); const uint64_t *p = api.getRawData(); Out << "static const ConstantFP80Ty FPConstant" << FPCounter++ - << " = { 0x" - << utohexstr((uint16_t)p[1] | (p[0] & 0xffffffffffffLL)<<16) - << "ULL, 0x" << utohexstr((uint16_t)(p[0] >> 48)) << ",{0,0,0}" + << " = { 0x" << utohexstr(p[0]) + << "ULL, 0x" << utohexstr((uint16_t)p[1]) << ",{0,0,0}" << "}; /* Long double constant */\n"; } else if (FPC->getType() == Type::PPC_FP128Ty) { APInt api = FPC->getValueAPF().bitcastToAPInt(); diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 1d52d63..3f8be47 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -797,9 +797,29 @@ static void WriteConstantInt(raw_ostream &Out, const Constant *CV, // Some form of long double. These appear as a magic letter identifying // the type, then a fixed number of hex digits. Out << "0x"; - if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended) + if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended) { Out << 'K'; - else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad) + // api needed to prevent premature destruction + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t* p = api.getRawData(); + uint64_t word = p[1]; + int shiftcount=12; + int width = api.getBitWidth(); + for (int j=0; j>shiftcount) & 15; + if (nibble < 10) + Out << (unsigned char)(nibble + '0'); + else + Out << (unsigned char)(nibble - 10 + 'A'); + if (shiftcount == 0 && j+4 < width) { + word = *p; + shiftcount = 64; + if (width-j-4 < 64) + shiftcount = width-j-4; + } + } + return; + } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad) Out << 'L'; else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) Out << 'M'; -- cgit v1.1