[llvm-commits] [llvm] r135888 - in /llvm/trunk: include/llvm/ADT/Twine.h lib/Support/Twine.cpp unittests/ADT/TwineTest.cpp

Chris Lattner sabre at nondot.org
Sun Jul 24 13:44:30 PDT 2011


Author: lattner
Date: Sun Jul 24 15:44:30 2011
New Revision: 135888

URL: http://llvm.org/viewvc/llvm-project?rev=135888&view=rev
Log:
Add Twine support for characters, and switch twine to use a union internally
to eliminate some casting.

Modified:
    llvm/trunk/include/llvm/ADT/Twine.h
    llvm/trunk/lib/Support/Twine.cpp
    llvm/trunk/unittests/ADT/TwineTest.cpp

Modified: llvm/trunk/include/llvm/ADT/Twine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/Twine.h?rev=135888&r1=135887&r2=135888&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/Twine.h (original)
+++ llvm/trunk/include/llvm/ADT/Twine.h Sun Jul 24 15:44:30 2011
@@ -99,6 +99,9 @@
       /// A pointer to a StringRef instance.
       StringRefKind,
 
+      /// A char value reinterpreted as a pointer, to render as a character.
+      CharKind,
+
       /// An unsigned int value reinterpreted as a pointer, to render as an
       /// unsigned decimal integer.
       DecUIKind,
@@ -126,13 +129,31 @@
       UHexKind
     };
 
+    union Child
+    {
+      const Twine *twine;
+      const char *cString;
+      const std::string *stdString;
+      const StringRef *stringRef;
+      char character;
+      unsigned int decUI;
+      int decI;
+      const unsigned long *decUL;
+      const long *decL;
+      const unsigned long long *decULL;
+      const long long *decLL;
+      const uint64_t *uHex;
+    };
+
   private:
     /// LHS - The prefix in the concatenation, which may be uninitialized for
     /// Null or Empty kinds.
-    const void *LHS;
+    Child LHS;
     /// RHS - The suffix in the concatenation, which may be uninitialized for
     /// Null or Empty kinds.
-    const void *RHS;
+    Child RHS;
+    // enums stored as unsigned chars to save on space while some compilers
+    // don't support specifying the backing type for an enum
     /// LHSKind - The NodeKind of the left hand side, \see getLHSKind().
     unsigned char LHSKind;
     /// RHSKind - The NodeKind of the left hand side, \see getLHSKind().
@@ -147,13 +168,15 @@
 
     /// Construct a binary twine.
     explicit Twine(const Twine &_LHS, const Twine &_RHS)
-      : LHS(&_LHS), RHS(&_RHS), LHSKind(TwineKind), RHSKind(TwineKind) {
+      : LHSKind(TwineKind), RHSKind(TwineKind) {
+      LHS.twine = &_LHS;
+      RHS.twine = &_RHS;
       assert(isValid() && "Invalid twine!");
     }
 
     /// Construct a twine from explicit values.
-    explicit Twine(const void *_LHS, NodeKind _LHSKind,
-                   const void *_RHS, NodeKind _RHSKind)
+    explicit Twine(Child _LHS, NodeKind _LHSKind,
+                   Child _RHS, NodeKind _RHSKind)
       : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) {
       assert(isValid() && "Invalid twine!");
     }
@@ -200,10 +223,10 @@
 
       // A twine child should always be binary.
       if (getLHSKind() == TwineKind &&
-          !static_cast<const Twine*>(LHS)->isBinary())
+          !LHS.twine->isBinary())
         return false;
       if (getRHSKind() == TwineKind &&
-          !static_cast<const Twine*>(RHS)->isBinary())
+          !RHS.twine->isBinary())
         return false;
 
       return true;
@@ -216,10 +239,10 @@
     NodeKind getRHSKind() const { return (NodeKind) RHSKind; }
 
     /// printOneChild - Print one child from a twine.
-    void printOneChild(raw_ostream &OS, const void *Ptr, NodeKind Kind) const;
+    void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
 
     /// printOneChildRepr - Print the representation of one child from a twine.
-    void printOneChildRepr(raw_ostream &OS, const void *Ptr,
+    void printOneChildRepr(raw_ostream &OS, Child Ptr,
                            NodeKind Kind) const;
 
   public:
@@ -239,7 +262,7 @@
     /*implicit*/ Twine(const char *Str)
       : RHSKind(EmptyKind) {
       if (Str[0] != '\0') {
-        LHS = Str;
+        LHS.cString = Str;
         LHSKind = CStringKind;
       } else
         LHSKind = EmptyKind;
@@ -249,44 +272,70 @@
 
     /// Construct from an std::string.
     /*implicit*/ Twine(const std::string &Str)
-      : LHS(&Str), LHSKind(StdStringKind), RHSKind(EmptyKind) {
+      : LHSKind(StdStringKind), RHSKind(EmptyKind) {
+      LHS.stdString = &Str;
       assert(isValid() && "Invalid twine!");
     }
 
     /// Construct from a StringRef.
     /*implicit*/ Twine(const StringRef &Str)
-      : LHS(&Str), LHSKind(StringRefKind), RHSKind(EmptyKind) {
+      : LHSKind(StringRefKind), RHSKind(EmptyKind) {
+      LHS.stringRef = &Str;
       assert(isValid() && "Invalid twine!");
     }
 
+    /// Construct from a char.
+    explicit Twine(char Val)
+      : LHSKind(CharKind), RHSKind(EmptyKind) {
+      LHS.character = Val;
+    }
+
+    /// Construct from a signed char.
+    explicit Twine(signed char Val)
+      : LHSKind(CharKind), RHSKind(EmptyKind) {
+      LHS.character = static_cast<char>(Val);
+    }
+
+    /// Construct from an unsigned char.
+    explicit Twine(unsigned char Val)
+      : LHSKind(CharKind), RHSKind(EmptyKind) {
+      LHS.character = static_cast<char>(Val);
+    }
+
     /// Construct a twine to print \arg Val as an unsigned decimal integer.
     explicit Twine(unsigned Val)
-      : LHS((void*)(intptr_t)Val), LHSKind(DecUIKind), RHSKind(EmptyKind) {
+      : LHSKind(DecUIKind), RHSKind(EmptyKind) {
+      LHS.decUI = Val;
     }
 
     /// Construct a twine to print \arg Val as a signed decimal integer.
     explicit Twine(int Val)
-      : LHS((void*)(intptr_t)Val), LHSKind(DecIKind), RHSKind(EmptyKind) {
+      : LHSKind(DecIKind), RHSKind(EmptyKind) {
+      LHS.decI = Val;
     }
 
     /// Construct a twine to print \arg Val as an unsigned decimal integer.
     explicit Twine(const unsigned long &Val)
-      : LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) {
+      : LHSKind(DecULKind), RHSKind(EmptyKind) {
+      LHS.decUL = &Val;
     }
 
     /// Construct a twine to print \arg Val as a signed decimal integer.
     explicit Twine(const long &Val)
-      : LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) {
+      : LHSKind(DecLKind), RHSKind(EmptyKind) {
+      LHS.decL = &Val;
     }
 
     /// Construct a twine to print \arg Val as an unsigned decimal integer.
     explicit Twine(const unsigned long long &Val)
-      : LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) {
+      : LHSKind(DecULLKind), RHSKind(EmptyKind) {
+      LHS.decULL = &Val;
     }
 
     /// Construct a twine to print \arg Val as a signed decimal integer.
     explicit Twine(const long long &Val)
-      : LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) {
+      : LHSKind(DecLLKind), RHSKind(EmptyKind) {
+      LHS.decLL = &Val;
     }
 
     // FIXME: Unfortunately, to make sure this is as efficient as possible we
@@ -296,13 +345,17 @@
 
     /// Construct as the concatenation of a C string and a StringRef.
     /*implicit*/ Twine(const char *_LHS, const StringRef &_RHS)
-      : LHS(_LHS), RHS(&_RHS), LHSKind(CStringKind), RHSKind(StringRefKind) {
+      : LHSKind(CStringKind), RHSKind(StringRefKind) {
+      LHS.cString = _LHS;
+      RHS.stringRef = &_RHS;
       assert(isValid() && "Invalid twine!");
     }
 
     /// Construct as the concatenation of a StringRef and a C string.
     /*implicit*/ Twine(const StringRef &_LHS, const char *_RHS)
-      : LHS(&_LHS), RHS(_RHS), LHSKind(StringRefKind), RHSKind(CStringKind) {
+      : LHSKind(StringRefKind), RHSKind(CStringKind) {
+      LHS.stringRef = &_LHS;
+      RHS.cString = _RHS;
       assert(isValid() && "Invalid twine!");
     }
 
@@ -318,7 +371,10 @@
 
     // Construct a twine to print \arg Val as an unsigned hexadecimal integer.
     static Twine utohexstr(const uint64_t &Val) {
-      return Twine(&Val, UHexKind, 0, EmptyKind);
+      Child LHS, RHS;
+      LHS.uHex = &Val;
+      RHS.twine = 0;
+      return Twine(LHS, UHexKind, RHS, EmptyKind);
     }
 
     /// @}
@@ -371,9 +427,9 @@
       switch (getLHSKind()) {
       default: assert(0 && "Out of sync with isSingleStringRef");
       case EmptyKind:      return StringRef();
-      case CStringKind:    return StringRef((const char*)LHS);
-      case StdStringKind:  return StringRef(*(const std::string*)LHS);
-      case StringRefKind:  return *(const StringRef*)LHS;
+      case CStringKind:    return StringRef(LHS.cString);
+      case StdStringKind:  return StringRef(*LHS.stdString);
+      case StringRefKind:  return *LHS.stringRef;
       }
     }
 
@@ -422,7 +478,9 @@
 
     // Otherwise we need to create a new node, taking care to fold in unary
     // twines.
-    const void *NewLHS = this, *NewRHS = &Suffix;
+    Child NewLHS, NewRHS;
+    NewLHS.twine = this;
+    NewRHS.twine = &Suffix;
     NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind;
     if (isUnary()) {
       NewLHS = LHS;

Modified: llvm/trunk/lib/Support/Twine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Twine.cpp?rev=135888&r1=135887&r2=135888&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Twine.cpp (original)
+++ llvm/trunk/lib/Support/Twine.cpp Sun Jul 24 15:44:30 2011
@@ -16,7 +16,7 @@
 std::string Twine::str() const {
   // If we're storing only a std::string, just return it.
   if (LHSKind == StdStringKind && RHSKind == EmptyKind)
-    return *static_cast<const std::string*>(LHS);
+    return *LHS.stdString;
 
   // Otherwise, flatten and copy the contents first.
   SmallString<256> Vec;
@@ -40,9 +40,9 @@
     switch (getLHSKind()) {
     case CStringKind:
       // Already null terminated, yay!
-      return StringRef(static_cast<const char*>(LHS));
+      return StringRef(LHS.cString);
     case StdStringKind: {
-      const std::string *str = static_cast<const std::string*>(LHS);
+      const std::string *str = LHS.stdString;
       return StringRef(str->c_str(), str->size());
     }
     default:
@@ -55,48 +55,51 @@
   return StringRef(Out.data(), Out.size());
 }
 
-void Twine::printOneChild(raw_ostream &OS, const void *Ptr,
+void Twine::printOneChild(raw_ostream &OS, Child Ptr,
                           NodeKind Kind) const {
   switch (Kind) {
   case Twine::NullKind: break;
   case Twine::EmptyKind: break;
   case Twine::TwineKind:
-    static_cast<const Twine*>(Ptr)->print(OS);
+    Ptr.twine->print(OS);
     break;
   case Twine::CStringKind:
-    OS << static_cast<const char*>(Ptr);
+    OS << Ptr.cString;
     break;
   case Twine::StdStringKind:
-    OS << *static_cast<const std::string*>(Ptr);
+    OS << *Ptr.stdString;
     break;
   case Twine::StringRefKind:
-    OS << *static_cast<const StringRef*>(Ptr);
+    OS << *Ptr.stringRef;
+    break;
+  case Twine::CharKind:
+    OS << Ptr.character;
     break;
   case Twine::DecUIKind:
-    OS << (unsigned)(uintptr_t)Ptr;
+    OS << Ptr.decUI;
     break;
   case Twine::DecIKind:
-    OS << (int)(intptr_t)Ptr;
+    OS << Ptr.decI;
     break;
   case Twine::DecULKind:
-    OS << *static_cast<const unsigned long*>(Ptr);
+    OS << *Ptr.decUL;
     break;
   case Twine::DecLKind:
-    OS << *static_cast<const long*>(Ptr);
+    OS << *Ptr.decL;
     break;
   case Twine::DecULLKind:
-    OS << *static_cast<const unsigned long long*>(Ptr);
+    OS << *Ptr.decULL;
     break;
   case Twine::DecLLKind:
-    OS << *static_cast<const long long*>(Ptr);
+    OS << *Ptr.decLL;
     break;
   case Twine::UHexKind:
-    OS.write_hex(*static_cast<const uint64_t*>(Ptr));
+    OS.write_hex(*Ptr.uHex);
     break;
   }
 }
 
-void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr,
+void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr,
                               NodeKind Kind) const {
   switch (Kind) {
   case Twine::NullKind:
@@ -105,40 +108,43 @@
     OS << "empty"; break;
   case Twine::TwineKind:
     OS << "rope:";
-    static_cast<const Twine*>(Ptr)->printRepr(OS);
+    Ptr.twine->printRepr(OS);
     break;
   case Twine::CStringKind:
     OS << "cstring:\""
-       << static_cast<const char*>(Ptr) << "\"";
+       << Ptr.cString << "\"";
     break;
   case Twine::StdStringKind:
     OS << "std::string:\""
-       << static_cast<const std::string*>(Ptr) << "\"";
+       << Ptr.stdString << "\"";
     break;
   case Twine::StringRefKind:
     OS << "stringref:\""
-       << static_cast<const StringRef*>(Ptr) << "\"";
+       << Ptr.stringRef << "\"";
+    break;
+  case Twine::CharKind:
+    OS << "char:\"" << Ptr.character << "\"";
     break;
   case Twine::DecUIKind:
-    OS << "decUI:\"" << (unsigned)(uintptr_t)Ptr << "\"";
+    OS << "decUI:\"" << Ptr.decUI << "\"";
     break;
   case Twine::DecIKind:
-    OS << "decI:\"" << (int)(intptr_t)Ptr << "\"";
+    OS << "decI:\"" << Ptr.decI << "\"";
     break;
   case Twine::DecULKind:
-    OS << "decUL:\"" << *static_cast<const unsigned long*>(Ptr) << "\"";
+    OS << "decUL:\"" << *Ptr.decUL << "\"";
     break;
   case Twine::DecLKind:
-    OS << "decL:\"" << *static_cast<const long*>(Ptr) << "\"";
+    OS << "decL:\"" << *Ptr.decL << "\"";
     break;
   case Twine::DecULLKind:
-    OS << "decULL:\"" << *static_cast<const unsigned long long*>(Ptr) << "\"";
+    OS << "decULL:\"" << *Ptr.decULL << "\"";
     break;
   case Twine::DecLLKind:
-    OS << "decLL:\"" << *static_cast<const long long*>(Ptr) << "\"";
+    OS << "decLL:\"" << *Ptr.decLL << "\"";
     break;
   case Twine::UHexKind:
-    OS << "uhex:\"" << static_cast<const uint64_t*>(Ptr) << "\"";
+    OS << "uhex:\"" << Ptr.uHex << "\"";
     break;
   }
 }

Modified: llvm/trunk/unittests/ADT/TwineTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/TwineTest.cpp?rev=135888&r1=135887&r2=135888&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/TwineTest.cpp (original)
+++ llvm/trunk/unittests/ADT/TwineTest.cpp Sun Jul 24 15:44:30 2011
@@ -37,12 +37,16 @@
   EXPECT_EQ("-123", Twine(-123).str());
   EXPECT_EQ("123", Twine(123).str());
   EXPECT_EQ("-123", Twine(-123).str());
-  EXPECT_EQ("123", Twine((char) 123).str());
-  EXPECT_EQ("-123", Twine((signed char) -123).str());
 
   EXPECT_EQ("7b", Twine::utohexstr(123).str());
 }
 
+TEST(TwineTest, Characters) {
+  EXPECT_EQ("x", Twine('x').str());
+  EXPECT_EQ("x", Twine(static_cast<unsigned char>('x')).str());
+  EXPECT_EQ("x", Twine(static_cast<signed char>('x')).str());
+}
+
 TEST(TwineTest, Concat) {
   // Check verse repr, since we care about the actual representation not just
   // the result.





More information about the llvm-commits mailing list