1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Add Twine support for characters, and switch twine to use a union internally

to eliminate some casting.

llvm-svn: 135888
This commit is contained in:
Chris Lattner 2011-07-24 20:44:30 +00:00
parent e00fa0544e
commit 0e3472660b
3 changed files with 122 additions and 54 deletions

View File

@ -99,6 +99,9 @@ namespace llvm {
/// A pointer to a StringRef instance. /// A pointer to a StringRef instance.
StringRefKind, 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 /// An unsigned int value reinterpreted as a pointer, to render as an
/// unsigned decimal integer. /// unsigned decimal integer.
DecUIKind, DecUIKind,
@ -126,13 +129,31 @@ namespace llvm {
UHexKind 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: private:
/// LHS - The prefix in the concatenation, which may be uninitialized for /// LHS - The prefix in the concatenation, which may be uninitialized for
/// Null or Empty kinds. /// Null or Empty kinds.
const void *LHS; Child LHS;
/// RHS - The suffix in the concatenation, which may be uninitialized for /// RHS - The suffix in the concatenation, which may be uninitialized for
/// Null or Empty kinds. /// 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(). /// LHSKind - The NodeKind of the left hand side, \see getLHSKind().
unsigned char LHSKind; unsigned char LHSKind;
/// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). /// RHSKind - The NodeKind of the left hand side, \see getLHSKind().
@ -147,13 +168,15 @@ namespace llvm {
/// Construct a binary twine. /// Construct a binary twine.
explicit Twine(const Twine &_LHS, const Twine &_RHS) 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!"); assert(isValid() && "Invalid twine!");
} }
/// Construct a twine from explicit values. /// Construct a twine from explicit values.
explicit Twine(const void *_LHS, NodeKind _LHSKind, explicit Twine(Child _LHS, NodeKind _LHSKind,
const void *_RHS, NodeKind _RHSKind) Child _RHS, NodeKind _RHSKind)
: LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) { : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) {
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
@ -200,10 +223,10 @@ namespace llvm {
// A twine child should always be binary. // A twine child should always be binary.
if (getLHSKind() == TwineKind && if (getLHSKind() == TwineKind &&
!static_cast<const Twine*>(LHS)->isBinary()) !LHS.twine->isBinary())
return false; return false;
if (getRHSKind() == TwineKind && if (getRHSKind() == TwineKind &&
!static_cast<const Twine*>(RHS)->isBinary()) !RHS.twine->isBinary())
return false; return false;
return true; return true;
@ -216,10 +239,10 @@ namespace llvm {
NodeKind getRHSKind() const { return (NodeKind) RHSKind; } NodeKind getRHSKind() const { return (NodeKind) RHSKind; }
/// printOneChild - Print one child from a twine. /// 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. /// 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; NodeKind Kind) const;
public: public:
@ -239,7 +262,7 @@ namespace llvm {
/*implicit*/ Twine(const char *Str) /*implicit*/ Twine(const char *Str)
: RHSKind(EmptyKind) { : RHSKind(EmptyKind) {
if (Str[0] != '\0') { if (Str[0] != '\0') {
LHS = Str; LHS.cString = Str;
LHSKind = CStringKind; LHSKind = CStringKind;
} else } else
LHSKind = EmptyKind; LHSKind = EmptyKind;
@ -249,44 +272,70 @@ namespace llvm {
/// Construct from an std::string. /// Construct from an std::string.
/*implicit*/ Twine(const std::string &Str) /*implicit*/ Twine(const std::string &Str)
: LHS(&Str), LHSKind(StdStringKind), RHSKind(EmptyKind) { : LHSKind(StdStringKind), RHSKind(EmptyKind) {
LHS.stdString = &Str;
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
/// Construct from a StringRef. /// Construct from a StringRef.
/*implicit*/ Twine(const StringRef &Str) /*implicit*/ Twine(const StringRef &Str)
: LHS(&Str), LHSKind(StringRefKind), RHSKind(EmptyKind) { : LHSKind(StringRefKind), RHSKind(EmptyKind) {
LHS.stringRef = &Str;
assert(isValid() && "Invalid twine!"); 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. /// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(unsigned Val) 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. /// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(int Val) 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. /// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(const unsigned long &Val) 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. /// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(const long &Val) 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. /// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(const unsigned long long &Val) 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. /// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(const long long &Val) 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 // FIXME: Unfortunately, to make sure this is as efficient as possible we
@ -296,13 +345,17 @@ namespace llvm {
/// Construct as the concatenation of a C string and a StringRef. /// Construct as the concatenation of a C string and a StringRef.
/*implicit*/ Twine(const char *_LHS, const StringRef &_RHS) /*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!"); assert(isValid() && "Invalid twine!");
} }
/// Construct as the concatenation of a StringRef and a C string. /// Construct as the concatenation of a StringRef and a C string.
/*implicit*/ Twine(const StringRef &_LHS, const char *_RHS) /*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!"); assert(isValid() && "Invalid twine!");
} }
@ -318,7 +371,10 @@ namespace llvm {
// Construct a twine to print \arg Val as an unsigned hexadecimal integer. // Construct a twine to print \arg Val as an unsigned hexadecimal integer.
static Twine utohexstr(const uint64_t &Val) { 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 @@ namespace llvm {
switch (getLHSKind()) { switch (getLHSKind()) {
default: assert(0 && "Out of sync with isSingleStringRef"); default: assert(0 && "Out of sync with isSingleStringRef");
case EmptyKind: return StringRef(); case EmptyKind: return StringRef();
case CStringKind: return StringRef((const char*)LHS); case CStringKind: return StringRef(LHS.cString);
case StdStringKind: return StringRef(*(const std::string*)LHS); case StdStringKind: return StringRef(*LHS.stdString);
case StringRefKind: return *(const StringRef*)LHS; case StringRefKind: return *LHS.stringRef;
} }
} }
@ -422,7 +478,9 @@ namespace llvm {
// Otherwise we need to create a new node, taking care to fold in unary // Otherwise we need to create a new node, taking care to fold in unary
// twines. // twines.
const void *NewLHS = this, *NewRHS = &Suffix; Child NewLHS, NewRHS;
NewLHS.twine = this;
NewRHS.twine = &Suffix;
NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind;
if (isUnary()) { if (isUnary()) {
NewLHS = LHS; NewLHS = LHS;

View File

@ -16,7 +16,7 @@ using namespace llvm;
std::string Twine::str() const { std::string Twine::str() const {
// If we're storing only a std::string, just return it. // If we're storing only a std::string, just return it.
if (LHSKind == StdStringKind && RHSKind == EmptyKind) if (LHSKind == StdStringKind && RHSKind == EmptyKind)
return *static_cast<const std::string*>(LHS); return *LHS.stdString;
// Otherwise, flatten and copy the contents first. // Otherwise, flatten and copy the contents first.
SmallString<256> Vec; SmallString<256> Vec;
@ -40,9 +40,9 @@ StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
switch (getLHSKind()) { switch (getLHSKind()) {
case CStringKind: case CStringKind:
// Already null terminated, yay! // Already null terminated, yay!
return StringRef(static_cast<const char*>(LHS)); return StringRef(LHS.cString);
case StdStringKind: { 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()); return StringRef(str->c_str(), str->size());
} }
default: default:
@ -55,48 +55,51 @@ StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
return StringRef(Out.data(), Out.size()); 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 { NodeKind Kind) const {
switch (Kind) { switch (Kind) {
case Twine::NullKind: break; case Twine::NullKind: break;
case Twine::EmptyKind: break; case Twine::EmptyKind: break;
case Twine::TwineKind: case Twine::TwineKind:
static_cast<const Twine*>(Ptr)->print(OS); Ptr.twine->print(OS);
break; break;
case Twine::CStringKind: case Twine::CStringKind:
OS << static_cast<const char*>(Ptr); OS << Ptr.cString;
break; break;
case Twine::StdStringKind: case Twine::StdStringKind:
OS << *static_cast<const std::string*>(Ptr); OS << *Ptr.stdString;
break; break;
case Twine::StringRefKind: case Twine::StringRefKind:
OS << *static_cast<const StringRef*>(Ptr); OS << *Ptr.stringRef;
break;
case Twine::CharKind:
OS << Ptr.character;
break; break;
case Twine::DecUIKind: case Twine::DecUIKind:
OS << (unsigned)(uintptr_t)Ptr; OS << Ptr.decUI;
break; break;
case Twine::DecIKind: case Twine::DecIKind:
OS << (int)(intptr_t)Ptr; OS << Ptr.decI;
break; break;
case Twine::DecULKind: case Twine::DecULKind:
OS << *static_cast<const unsigned long*>(Ptr); OS << *Ptr.decUL;
break; break;
case Twine::DecLKind: case Twine::DecLKind:
OS << *static_cast<const long*>(Ptr); OS << *Ptr.decL;
break; break;
case Twine::DecULLKind: case Twine::DecULLKind:
OS << *static_cast<const unsigned long long*>(Ptr); OS << *Ptr.decULL;
break; break;
case Twine::DecLLKind: case Twine::DecLLKind:
OS << *static_cast<const long long*>(Ptr); OS << *Ptr.decLL;
break; break;
case Twine::UHexKind: case Twine::UHexKind:
OS.write_hex(*static_cast<const uint64_t*>(Ptr)); OS.write_hex(*Ptr.uHex);
break; break;
} }
} }
void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr, void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr,
NodeKind Kind) const { NodeKind Kind) const {
switch (Kind) { switch (Kind) {
case Twine::NullKind: case Twine::NullKind:
@ -105,40 +108,43 @@ void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr,
OS << "empty"; break; OS << "empty"; break;
case Twine::TwineKind: case Twine::TwineKind:
OS << "rope:"; OS << "rope:";
static_cast<const Twine*>(Ptr)->printRepr(OS); Ptr.twine->printRepr(OS);
break; break;
case Twine::CStringKind: case Twine::CStringKind:
OS << "cstring:\"" OS << "cstring:\""
<< static_cast<const char*>(Ptr) << "\""; << Ptr.cString << "\"";
break; break;
case Twine::StdStringKind: case Twine::StdStringKind:
OS << "std::string:\"" OS << "std::string:\""
<< static_cast<const std::string*>(Ptr) << "\""; << Ptr.stdString << "\"";
break; break;
case Twine::StringRefKind: case Twine::StringRefKind:
OS << "stringref:\"" OS << "stringref:\""
<< static_cast<const StringRef*>(Ptr) << "\""; << Ptr.stringRef << "\"";
break;
case Twine::CharKind:
OS << "char:\"" << Ptr.character << "\"";
break; break;
case Twine::DecUIKind: case Twine::DecUIKind:
OS << "decUI:\"" << (unsigned)(uintptr_t)Ptr << "\""; OS << "decUI:\"" << Ptr.decUI << "\"";
break; break;
case Twine::DecIKind: case Twine::DecIKind:
OS << "decI:\"" << (int)(intptr_t)Ptr << "\""; OS << "decI:\"" << Ptr.decI << "\"";
break; break;
case Twine::DecULKind: case Twine::DecULKind:
OS << "decUL:\"" << *static_cast<const unsigned long*>(Ptr) << "\""; OS << "decUL:\"" << *Ptr.decUL << "\"";
break; break;
case Twine::DecLKind: case Twine::DecLKind:
OS << "decL:\"" << *static_cast<const long*>(Ptr) << "\""; OS << "decL:\"" << *Ptr.decL << "\"";
break; break;
case Twine::DecULLKind: case Twine::DecULLKind:
OS << "decULL:\"" << *static_cast<const unsigned long long*>(Ptr) << "\""; OS << "decULL:\"" << *Ptr.decULL << "\"";
break; break;
case Twine::DecLLKind: case Twine::DecLLKind:
OS << "decLL:\"" << *static_cast<const long long*>(Ptr) << "\""; OS << "decLL:\"" << *Ptr.decLL << "\"";
break; break;
case Twine::UHexKind: case Twine::UHexKind:
OS << "uhex:\"" << static_cast<const uint64_t*>(Ptr) << "\""; OS << "uhex:\"" << Ptr.uHex << "\"";
break; break;
} }
} }

View File

@ -37,12 +37,16 @@ TEST(TwineTest, Numbers) {
EXPECT_EQ("-123", Twine(-123).str()); EXPECT_EQ("-123", Twine(-123).str());
EXPECT_EQ("123", Twine(123).str()); 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()); 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) { TEST(TwineTest, Concat) {
// Check verse repr, since we care about the actual representation not just // Check verse repr, since we care about the actual representation not just
// the result. // the result.