mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
Add Twine support for characters, and switch twine to use a union internally
to eliminate some casting. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135888 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
81d686edbe
commit
3f25ee080c
@ -99,6 +99,9 @@ namespace llvm {
|
||||
/// 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 @@ namespace llvm {
|
||||
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 @@ 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!");
|
||||
}
|
||||
@ -200,10 +223,10 @@ namespace llvm {
|
||||
|
||||
// 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 @@ namespace llvm {
|
||||
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 @@ namespace llvm {
|
||||
/*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 @@ 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<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 @@ 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!");
|
||||
}
|
||||
|
||||
@ -318,7 +371,10 @@ 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);
|
||||
}
|
||||
|
||||
/// @}
|
||||
@ -371,9 +427,9 @@ namespace llvm {
|
||||
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 @@ 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;
|
||||
|
@ -16,7 +16,7 @@ using namespace llvm;
|
||||
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 @@ StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
|
||||
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 @@ StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
|
||||
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 @@ void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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((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.
|
||||
|
Loading…
Reference in New Issue
Block a user