From a023b6924a4c9cf4bb39af16be0556cbee099d52 Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 30 Jan 2012 18:36:31 +0000 Subject: [PATCH] Per discussion on cxx-abi-dev, don't drop leading zeroes from the mangling of floating-point literals. I just went ahead and reimplemented toString() here; if someone wants to generalize the library routine to do this, or feels strongly that we should be post-processing, please feel free. llvm-svn: 149256 --- clang/lib/AST/ItaniumMangle.cpp | 42 +++++++++++++++++++++++++------- clang/test/CodeGenCXX/mangle.cpp | 8 ++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 427be32a4607..fabf8cf0030d 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -610,17 +610,41 @@ void CXXNameMangler::mangleFloat(const llvm::APFloat &f) { // representation (IEEE on Itanium), high-order bytes first, // without leading zeroes. For example: "Lf bf800000 E" is -1.0f // on Itanium. - // APInt::toString uses uppercase hexadecimal, and it's not really - // worth embellishing that interface for this use case, so we just - // do a second pass to lowercase things. - typedef llvm::SmallString<20> buffer_t; - buffer_t buffer; - f.bitcastToAPInt().toString(buffer, 16, false); + // The 'without leading zeroes' thing seems to be an editorial + // mistake; see the discussion on cxx-abi-dev beginning on + // 2012-01-16. - for (buffer_t::iterator i = buffer.begin(), e = buffer.end(); i != e; ++i) - if (isupper(*i)) *i = tolower(*i); + // Our requirements here are just barely wierd enough to justify + // using a custom algorithm instead of post-processing APInt::toString(). - Out.write(buffer.data(), buffer.size()); + llvm::APInt valueBits = f.bitcastToAPInt(); + unsigned numCharacters = (valueBits.getBitWidth() + 3) / 4; + assert(numCharacters != 0); + + // Allocate a buffer of the right number of characters. + llvm::SmallVector buffer; + buffer.set_size(numCharacters); + + // Fill the buffer left-to-right. + for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) { + // The bit-index of the next hex digit. + unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1); + + // Project out 4 bits starting at 'digitIndex'. + llvm::integerPart hexDigit + = valueBits.getRawData()[digitBitIndex / llvm::integerPartWidth]; + hexDigit >>= (digitBitIndex % llvm::integerPartWidth); + hexDigit &= 0xF; + + // Map that over to a lowercase hex digit. + static const char charForHex[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + buffer[stringIndex] = charForHex[hexDigit]; + } + + Out.write(buffer.data(), numCharacters); } void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) { diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index 17232fd060ee..ba1b3bf5acd2 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -361,6 +361,14 @@ namespace test0 { j(buffer); } // CHECK: define linkonce_odr void @_ZN5test01jINS_1AEEEvRAszdtcvT__E6buffer_c( + + template void k(char (&buffer)[sizeof(T() + 0.0f)]) {} + void test5() { + char buffer[sizeof(float)]; + k(buffer); + } + // CHECK: define linkonce_odr void @_ZN5test01kIfEEvRAszplcvT__ELf00000000E_c( + } namespace test1 {