X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FADT%2FTwine.h;h=9101df8cee37b36820befb864be187af5f1783b6;hb=b4c28fc93f5149a0bd7967af44c429412e751c56;hp=3022812331824424d71ebbf81db78effe89b0214;hpb=0165a2ca897598bb95baec031362921565e24f2b;p=oota-llvm.git diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 30228123318..9101df8cee3 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -12,6 +12,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include #include @@ -42,7 +43,7 @@ namespace llvm { /// Twines support a special 'null' value, which always concatenates to form /// itself, and renders as an empty string. This can be returned from APIs to /// effectively nullify any concatenations performed on the result. - /// + /// /// \b Implementation \n /// /// Given the nature of a Twine, it is not possible for the Twine's @@ -99,36 +100,65 @@ namespace llvm { /// A pointer to a StringRef instance. StringRefKind, - /// A pointer to a uint64_t value, to render as an unsigned decimal - /// integer. - UDec32Kind, + /// A char value reinterpreted as a pointer, to render as a character. + CharKind, - /// A pointer to a uint64_t value, to render as a signed decimal integer. - SDec32Kind, + /// An unsigned int value reinterpreted as a pointer, to render as an + /// unsigned decimal integer. + DecUIKind, - /// A pointer to a uint64_t value, to render as an unsigned decimal + /// An int value reinterpreted as a pointer, to render as a signed + /// decimal integer. + DecIKind, + + /// A pointer to an unsigned long value, to render as an unsigned decimal /// integer. - UDec64Kind, + DecULKind, + + /// A pointer to a long value, to render as a signed decimal integer. + DecLKind, - /// A pointer to a uint64_t value, to render as a signed decimal integer. - SDec64Kind, + /// A pointer to an unsigned long long value, to render as an unsigned + /// decimal integer. + DecULLKind, + + /// A pointer to a long long value, to render as a signed decimal integer. + DecLLKind, /// A pointer to a uint64_t value, to render as an unsigned hexadecimal /// integer. 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(). - NodeKind LHSKind : 8; + unsigned char LHSKind; /// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). - NodeKind RHSKind : 8; + unsigned char RHSKind; private: /// Construct a nullary twine; the kind must be NullKind or EmptyKind. @@ -139,13 +169,15 @@ namespace llvm { /// 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!"); } @@ -192,26 +224,26 @@ namespace llvm { // A twine child should always be binary. if (getLHSKind() == TwineKind && - !static_cast(LHS)->isBinary()) + !LHS.twine->isBinary()) return false; if (getRHSKind() == TwineKind && - !static_cast(RHS)->isBinary()) + !RHS.twine->isBinary()) return false; return true; } /// getLHSKind - Get the NodeKind of the left-hand side. - NodeKind getLHSKind() const { return LHSKind; } + NodeKind getLHSKind() const { return (NodeKind) LHSKind; } /// getRHSKind - Get the NodeKind of the left-hand side. - NodeKind getRHSKind() const { return RHSKind; } + 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: @@ -231,7 +263,7 @@ namespace llvm { /*implicit*/ Twine(const char *Str) : RHSKind(EmptyKind) { if (Str[0] != '\0') { - LHS = Str; + LHS.cString = Str; LHSKind = CStringKind; } else LHSKind = EmptyKind; @@ -241,34 +273,70 @@ namespace llvm { /// 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(Val); + } + + /// Construct from an unsigned char. + explicit Twine(unsigned char Val) + : LHSKind(CharKind), RHSKind(EmptyKind) { + LHS.character = static_cast(Val); + } + + /// Construct a twine to print \arg Val as an unsigned decimal integer. + explicit Twine(unsigned Val) + : LHSKind(DecUIKind), RHSKind(EmptyKind) { + LHS.decUI = Val; + } + + /// Construct a twine to print \arg Val as a signed decimal integer. + explicit Twine(int Val) + : LHSKind(DecIKind), RHSKind(EmptyKind) { + LHS.decI = Val; + } + /// Construct a twine to print \arg Val as an unsigned decimal integer. - Twine(const uint32_t &Val) - : LHS(&Val), LHSKind(UDec32Kind), RHSKind(EmptyKind) { + explicit Twine(const unsigned long &Val) + : LHSKind(DecULKind), RHSKind(EmptyKind) { + LHS.decUL = &Val; } /// Construct a twine to print \arg Val as a signed decimal integer. - Twine(const int32_t &Val) - : LHS(&Val), LHSKind(SDec32Kind), RHSKind(EmptyKind) { + explicit Twine(const long &Val) + : LHSKind(DecLKind), RHSKind(EmptyKind) { + LHS.decL = &Val; } /// Construct a twine to print \arg Val as an unsigned decimal integer. - Twine(const uint64_t &Val) - : LHS(&Val), LHSKind(UDec64Kind), RHSKind(EmptyKind) { + explicit Twine(const unsigned long long &Val) + : LHSKind(DecULLKind), RHSKind(EmptyKind) { + LHS.decULL = &Val; } /// Construct a twine to print \arg Val as a signed decimal integer. - Twine(const int64_t &Val) - : LHS(&Val), LHSKind(SDec64Kind), RHSKind(EmptyKind) { + explicit Twine(const long long &Val) + : LHSKind(DecLLKind), RHSKind(EmptyKind) { + LHS.decLL = &Val; } // FIXME: Unfortunately, to make sure this is as efficient as possible we @@ -278,13 +346,17 @@ namespace llvm { /// 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!"); } @@ -300,14 +372,36 @@ namespace llvm { // 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); } - // Construct a twine to print \arg Val as an unsigned hexadecimal - // integer. This routine is provided as a convenience to sign extend values - // before printing. - static Twine itohexstr(const int64_t &Val) { - return Twine(&Val, UHexKind, 0, EmptyKind); + /// @} + /// @name Predicate Operations + /// @{ + + /// isTriviallyEmpty - Check if this twine is trivially empty; a false + /// return value does not necessarily mean the twine is empty. + bool isTriviallyEmpty() const { + return isNullary(); + } + + /// isSingleStringRef - Return true if this twine can be dynamically + /// accessed as a single StringRef value with getSingleStringRef(). + bool isSingleStringRef() const { + if (getRHSKind() != EmptyKind) return false; + + switch (getLHSKind()) { + case EmptyKind: + case CStringKind: + case StdStringKind: + case StringRefKind: + return true; + default: + return false; + } } /// @} @@ -327,6 +421,32 @@ namespace llvm { /// SmallVector. void toVector(SmallVectorImpl &Out) const; + /// getSingleStringRef - This returns the twine as a single StringRef. This + /// method is only valid if isSingleStringRef() is true. + StringRef getSingleStringRef() const { + assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); + switch (getLHSKind()) { + default: llvm_unreachable("Out of sync with isSingleStringRef"); + case EmptyKind: return StringRef(); + case CStringKind: return StringRef(LHS.cString); + case StdStringKind: return StringRef(*LHS.stdString); + case StringRefKind: return *LHS.stringRef; + } + } + + /// toStringRef - This returns the twine as a single StringRef if it can be + /// represented as such. Otherwise the twine is written into the given + /// SmallVector and a StringRef to the SmallVector's data is returned. + StringRef toStringRef(SmallVectorImpl &Out) const; + + /// toNullTerminatedStringRef - This returns the twine as a single null + /// terminated StringRef if it can be represented as such. Otherwise the + /// twine is written into the given SmallVector and a StringRef to the + /// SmallVector's data is returned. + /// + /// The returned StringRef's size does not include the null terminator. + StringRef toNullTerminatedStringRef(SmallVectorImpl &Out) const; + /// print - Write the concatenated string represented by this twine to the /// stream \arg OS. void print(raw_ostream &OS) const; @@ -359,7 +479,9 @@ namespace llvm { // 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;