diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 5a38e6090f7..95e6c90a59c 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 adf053cf9b0..995aa4eb079 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 299ce0b94a4..69eadd9ee41 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 1055564be21..d4d3443ee05 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 2a64524860e..79d14f7aeb6 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"; @@ -1057,19 +1060,13 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, << '\t' << TAI->getCommentString() << " 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"; @@ -1077,6 +1074,9 @@ void AsmPrinter::EmitGlobalConstantFP(const ConstantFP *CFP, << '\t' << TAI->getCommentString() << " 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"; } diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index d7f0d821598..2ee6a276fdf 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 53c98640968..fc99f503f1d 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 1d52d639577..3f8be4781f3 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'; diff --git a/test/CodeGen/X86/2009-03-23-i80-fp80.ll b/test/CodeGen/X86/2009-03-23-i80-fp80.ll new file mode 100644 index 00000000000..0619e120396 --- /dev/null +++ b/test/CodeGen/X86/2009-03-23-i80-fp80.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep 302245289961712575840256 +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep K40018000000000000000 +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i686-apple-darwin9" + +define i80 @from() { + %tmp = bitcast x86_fp80 0xK4000C000000000000000 to i80 + ret i80 %tmp +} + +define x86_fp80 @to() { + %tmp = bitcast i80 302259125019767858003968 to x86_fp80 + ret x86_fp80 %tmp +}