Teach Twine to support SmallString.

Enable removing .str() member calls for these frequent cases. 

 http://reviews.llvm.org/D6372



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232465 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Yaron Keren
2015-03-17 09:51:17 +00:00
parent c57441f716
commit 0401f798d1
7 changed files with 78 additions and 64 deletions

View File

@@ -10,6 +10,7 @@
#ifndef LLVM_ADT_TWINE_H #ifndef LLVM_ADT_TWINE_H
#define LLVM_ADT_TWINE_H #define LLVM_ADT_TWINE_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@@ -17,9 +18,6 @@
#include <string> #include <string>
namespace llvm { namespace llvm {
template <typename T>
class SmallVectorImpl;
class StringRef;
class raw_ostream; class raw_ostream;
/// Twine - A lightweight data structure for efficiently representing the /// Twine - A lightweight data structure for efficiently representing the
@@ -100,6 +98,9 @@ namespace llvm {
/// A pointer to a StringRef instance. /// A pointer to a StringRef instance.
StringRefKind, StringRefKind,
/// A pointer to a SmallString instance.
SmallStringKind,
/// A char value reinterpreted as a pointer, to render as a character. /// A char value reinterpreted as a pointer, to render as a character.
CharKind, CharKind,
@@ -136,6 +137,7 @@ namespace llvm {
const char *cString; const char *cString;
const std::string *stdString; const std::string *stdString;
const StringRef *stringRef; const StringRef *stringRef;
const SmallVectorImpl<char> *smallString;
char character; char character;
unsigned int decUI; unsigned int decUI;
int decI; int decI;
@@ -183,32 +185,32 @@ namespace llvm {
/// when concatenating might cause undefined behavior or stack corruptions /// when concatenating might cause undefined behavior or stack corruptions
Twine &operator=(const Twine &Other) = delete; Twine &operator=(const Twine &Other) = delete;
/// isNull - Check for the null twine. /// Check for the null twine.
bool isNull() const { bool isNull() const {
return getLHSKind() == NullKind; return getLHSKind() == NullKind;
} }
/// isEmpty - Check for the empty twine. /// Check for the empty twine.
bool isEmpty() const { bool isEmpty() const {
return getLHSKind() == EmptyKind; return getLHSKind() == EmptyKind;
} }
/// isNullary - Check if this is a nullary twine (null or empty). /// Check if this is a nullary twine (null or empty).
bool isNullary() const { bool isNullary() const {
return isNull() || isEmpty(); return isNull() || isEmpty();
} }
/// isUnary - Check if this is a unary twine. /// Check if this is a unary twine.
bool isUnary() const { bool isUnary() const {
return getRHSKind() == EmptyKind && !isNullary(); return getRHSKind() == EmptyKind && !isNullary();
} }
/// isBinary - Check if this is a binary twine. /// Check if this is a binary twine.
bool isBinary() const { bool isBinary() const {
return getLHSKind() != NullKind && getRHSKind() != EmptyKind; return getLHSKind() != NullKind && getRHSKind() != EmptyKind;
} }
/// isValid - Check if this is a valid twine (satisfying the invariants on /// Check if this is a valid twine (satisfying the invariants on
/// order and number of arguments). /// order and number of arguments).
bool isValid() const { bool isValid() const {
// Nullary twines always have Empty on the RHS. // Nullary twines always have Empty on the RHS.
@@ -234,16 +236,16 @@ namespace llvm {
return true; return true;
} }
/// getLHSKind - Get the NodeKind of the left-hand side. /// Get the NodeKind of the left-hand side.
NodeKind getLHSKind() const { return LHSKind; } NodeKind getLHSKind() const { return LHSKind; }
/// getRHSKind - Get the NodeKind of the right-hand side. /// Get the NodeKind of the right-hand side.
NodeKind getRHSKind() const { return RHSKind; } NodeKind getRHSKind() const { return RHSKind; }
/// printOneChild - Print one child from a twine. /// Print one child from a twine.
void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
/// printOneChildRepr - Print the representation of one child from a twine. /// Print the representation of one child from a twine.
void printOneChildRepr(raw_ostream &OS, Child Ptr, void printOneChildRepr(raw_ostream &OS, Child Ptr,
NodeKind Kind) const; NodeKind Kind) const;
@@ -288,6 +290,13 @@ namespace llvm {
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
/// Construct from a SmallString.
/*implicit*/ Twine(const SmallVectorImpl<char> &Str)
: LHSKind(SmallStringKind), RHSKind(EmptyKind) {
LHS.smallString = &Str;
assert(isValid() && "Invalid twine!");
}
/// Construct from a char. /// Construct from a char.
explicit Twine(char Val) explicit Twine(char Val)
: LHSKind(CharKind), RHSKind(EmptyKind) { : LHSKind(CharKind), RHSKind(EmptyKind) {
@@ -385,14 +394,14 @@ namespace llvm {
/// @name Predicate Operations /// @name Predicate Operations
/// @{ /// @{
/// isTriviallyEmpty - Check if this twine is trivially empty; a false /// Check if this twine is trivially empty; a false return value does not
/// return value does not necessarily mean the twine is empty. /// necessarily mean the twine is empty.
bool isTriviallyEmpty() const { bool isTriviallyEmpty() const {
return isNullary(); return isNullary();
} }
/// isSingleStringRef - Return true if this twine can be dynamically /// Return true if this twine can be dynamically accessed as a single
/// accessed as a single StringRef value with getSingleStringRef(). /// StringRef value with getSingleStringRef().
bool isSingleStringRef() const { bool isSingleStringRef() const {
if (getRHSKind() != EmptyKind) return false; if (getRHSKind() != EmptyKind) return false;
@@ -401,6 +410,7 @@ namespace llvm {
case CStringKind: case CStringKind:
case StdStringKind: case StdStringKind:
case StringRefKind: case StringRefKind:
case SmallStringKind:
return true; return true;
default: default:
return false; return false;
@@ -417,15 +427,14 @@ namespace llvm {
/// @name Output & Conversion. /// @name Output & Conversion.
/// @{ /// @{
/// str - Return the twine contents as a std::string. /// Return the twine contents as a std::string.
std::string str() const; std::string str() const;
/// toVector - Write the concatenated string into the given SmallString or /// Write the concatenated string into the given SmallString or SmallVector.
/// SmallVector.
void toVector(SmallVectorImpl<char> &Out) const; void toVector(SmallVectorImpl<char> &Out) const;
/// getSingleStringRef - This returns the twine as a single StringRef. This /// This returns the twine as a single StringRef. This method is only valid
/// method is only valid if isSingleStringRef() is true. /// if isSingleStringRef() is true.
StringRef getSingleStringRef() const { StringRef getSingleStringRef() const {
assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
switch (getLHSKind()) { switch (getLHSKind()) {
@@ -434,18 +443,24 @@ namespace llvm {
case CStringKind: return StringRef(LHS.cString); case CStringKind: return StringRef(LHS.cString);
case StdStringKind: return StringRef(*LHS.stdString); case StdStringKind: return StringRef(*LHS.stdString);
case StringRefKind: return *LHS.stringRef; case StringRefKind: return *LHS.stringRef;
case SmallStringKind:
return StringRef(LHS.smallString->data(), LHS.smallString->size());
} }
} }
/// toStringRef - This returns the twine as a single StringRef if it can be /// This returns the twine as a single StringRef if it can be
/// represented as such. Otherwise the twine is written into the given /// represented as such. Otherwise the twine is written into the given
/// SmallVector and a StringRef to the SmallVector's data is returned. /// SmallVector and a StringRef to the SmallVector's data is returned.
StringRef toStringRef(SmallVectorImpl<char> &Out) const; StringRef toStringRef(SmallVectorImpl<char> &Out) const {
if (isSingleStringRef())
return getSingleStringRef();
toVector(Out);
return StringRef(Out.data(), Out.size());
}
/// toNullTerminatedStringRef - This returns the twine as a single null /// This returns the twine as a single null terminated StringRef if it
/// terminated StringRef if it can be represented as such. Otherwise the /// can be represented as such. Otherwise the twine is written into the
/// twine is written into the given SmallVector and a StringRef to the /// given SmallVector and a StringRef to the SmallVector's data is returned.
/// SmallVector's data is returned.
/// ///
/// The returned StringRef's size does not include the null terminator. /// The returned StringRef's size does not include the null terminator.
StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const; StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const;

View File

@@ -15,6 +15,7 @@
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCDwarf.h"
#include "llvm/MC/SectionKind.h" #include "llvm/MC/SectionKind.h"
#include "llvm/Support/Allocator.h" #include "llvm/Support/Allocator.h"
@@ -36,8 +37,6 @@ namespace llvm {
class MCRegisterInfo; class MCRegisterInfo;
class MCLineSection; class MCLineSection;
class SMLoc; class SMLoc;
class StringRef;
class Twine;
class MCSectionMachO; class MCSectionMachO;
class MCSectionELF; class MCSectionELF;
class MCSectionCOFF; class MCSectionCOFF;
@@ -230,7 +229,6 @@ namespace llvm {
/// return it. If not, create a forward reference and return it. /// return it. If not, create a forward reference and return it.
/// ///
/// @param Name - The symbol name, which must be unique across all symbols. /// @param Name - The symbol name, which must be unique across all symbols.
MCSymbol *GetOrCreateSymbol(StringRef Name);
MCSymbol *GetOrCreateSymbol(const Twine &Name); MCSymbol *GetOrCreateSymbol(const Twine &Name);
MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section);

View File

@@ -11,7 +11,9 @@
#define LLVM_OPTION_ARGLIST_H #define LLVM_OPTION_ARGLIST_H
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/OptSpecifier.h" #include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/Option.h" #include "llvm/Option/Option.h"
#include <list> #include <list>
@@ -277,16 +279,13 @@ public:
/// @name Arg Synthesis /// @name Arg Synthesis
/// @{ /// @{
/// MakeArgString - Construct a constant string pointer whose /// Construct a constant string pointer whose
/// lifetime will match that of the ArgList. /// lifetime will match that of the ArgList.
virtual const char *MakeArgString(StringRef Str) const = 0; virtual const char *MakeArgStringRef(StringRef Str) const = 0;
const char *MakeArgString(const char *Str) const { const char *MakeArgString(const Twine &Str) const {
return MakeArgString(StringRef(Str)); SmallString<256> Buf;
return MakeArgStringRef(Str.toStringRef(Buf));
} }
const char *MakeArgString(std::string Str) const {
return MakeArgString(StringRef(Str));
}
const char *MakeArgString(const Twine &Str) const;
/// \brief Create an arg string for (\p LHS + \p RHS), reusing the /// \brief Create an arg string for (\p LHS + \p RHS), reusing the
/// string at \p Index if possible. /// string at \p Index if possible.
@@ -336,7 +335,7 @@ public:
unsigned MakeIndex(StringRef String0, StringRef String1) const; unsigned MakeIndex(StringRef String0, StringRef String1) const;
using ArgList::MakeArgString; using ArgList::MakeArgString;
const char *MakeArgString(StringRef Str) const override; const char *MakeArgStringRef(StringRef Str) const override;
/// @} /// @}
}; };
@@ -374,7 +373,7 @@ public:
void AddSynthesizedArg(Arg *A); void AddSynthesizedArg(Arg *A);
using ArgList::MakeArgString; using ArgList::MakeArgString;
const char *MakeArgString(StringRef Str) const override; const char *MakeArgStringRef(StringRef Str) const override;
/// AddFlagArg - Construct a new FlagArg for the given option \p Id and /// AddFlagArg - Construct a new FlagArg for the given option \p Id and
/// append it to the argument list. /// append it to the argument list.

View File

@@ -98,13 +98,15 @@ void MCContext::reset() {
// Symbol Manipulation // Symbol Manipulation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) { MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) {
assert(!Name.empty() && "Normal symbols cannot be unnamed!"); SmallString<128> NameSV;
StringRef NameRef = Name.toStringRef(NameSV);
MCSymbol *&Sym = Symbols[Name]; assert(!NameRef.empty() && "Normal symbols cannot be unnamed!");
MCSymbol *&Sym = Symbols[NameRef];
if (!Sym) if (!Sym)
Sym = CreateSymbol(Name); Sym = CreateSymbol(NameRef);
return Sym; return Sym;
} }
@@ -168,11 +170,6 @@ MCSymbol *MCContext::createTempSymbol(const Twine &Name) {
return CreateSymbol(NameSV); return CreateSymbol(NameSV);
} }
MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) {
SmallString<128> NameSV;
return GetOrCreateSymbol(Name.toStringRef(NameSV));
}
MCSymbol *MCContext::CreateLinkerPrivateTempSymbol() { MCSymbol *MCContext::CreateLinkerPrivateTempSymbol() {
SmallString<128> NameSV; SmallString<128> NameSV;
raw_svector_ostream(NameSV) raw_svector_ostream(NameSV)

View File

@@ -285,11 +285,6 @@ void ArgList::ClaimAllArgs() const {
(*it)->claim(); (*it)->claim();
} }
const char *ArgList::MakeArgString(const Twine &T) const {
SmallString<256> Str;
return MakeArgString(T.toStringRef(Str));
}
const char *ArgList::GetOrMakeJoinedArgString(unsigned Index, const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
StringRef LHS, StringRef LHS,
StringRef RHS) const { StringRef RHS) const {
@@ -334,7 +329,7 @@ unsigned InputArgList::MakeIndex(StringRef String0,
return Index0; return Index0;
} }
const char *InputArgList::MakeArgString(StringRef Str) const { const char *InputArgList::MakeArgStringRef(StringRef Str) const {
return getArgString(MakeIndex(Str)); return getArgString(MakeIndex(Str));
} }
@@ -345,7 +340,7 @@ DerivedArgList::DerivedArgList(const InputArgList &BaseArgs)
DerivedArgList::~DerivedArgList() {} DerivedArgList::~DerivedArgList() {}
const char *DerivedArgList::MakeArgString(StringRef Str) const { const char *DerivedArgList::MakeArgStringRef(StringRef Str) const {
return BaseArgs.MakeArgString(Str); return BaseArgs.MakeArgString(Str);
} }

View File

@@ -28,13 +28,6 @@ void Twine::toVector(SmallVectorImpl<char> &Out) const {
print(OS); print(OS);
} }
StringRef Twine::toStringRef(SmallVectorImpl<char> &Out) const {
if (isSingleStringRef())
return getSingleStringRef();
toVector(Out);
return StringRef(Out.data(), Out.size());
}
StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const { StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
if (isUnary()) { if (isUnary()) {
switch (getLHSKind()) { switch (getLHSKind()) {
@@ -72,6 +65,9 @@ void Twine::printOneChild(raw_ostream &OS, Child Ptr,
case Twine::StringRefKind: case Twine::StringRefKind:
OS << *Ptr.stringRef; OS << *Ptr.stringRef;
break; break;
case Twine::SmallStringKind:
OS << *Ptr.smallString;
break;
case Twine::CharKind: case Twine::CharKind:
OS << Ptr.character; OS << Ptr.character;
break; break;
@@ -122,6 +118,10 @@ void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr,
OS << "stringref:\"" OS << "stringref:\""
<< Ptr.stringRef << "\""; << Ptr.stringRef << "\"";
break; break;
case Twine::SmallStringKind:
OS << "smallstring:\""
<< *Ptr.smallString << "\"";
break;
case Twine::CharKind: case Twine::CharKind:
OS << "char:\"" << Ptr.character << "\""; OS << "char:\"" << Ptr.character << "\"";
break; break;

View File

@@ -29,6 +29,7 @@ TEST(TwineTest, Construction) {
EXPECT_EQ("hi", Twine(StringRef("hi")).str()); EXPECT_EQ("hi", Twine(StringRef("hi")).str());
EXPECT_EQ("hi", Twine(StringRef(std::string("hi"))).str()); EXPECT_EQ("hi", Twine(StringRef(std::string("hi"))).str());
EXPECT_EQ("hi", Twine(StringRef("hithere", 2)).str()); EXPECT_EQ("hi", Twine(StringRef("hithere", 2)).str());
EXPECT_EQ("hi", Twine(SmallString<4>("hi")).str());
} }
TEST(TwineTest, Numbers) { TEST(TwineTest, Numbers) {
@@ -62,6 +63,10 @@ TEST(TwineTest, Concat) {
repr(Twine("hi").concat(Twine()))); repr(Twine("hi").concat(Twine())));
EXPECT_EQ("(Twine cstring:\"hi\" empty)", EXPECT_EQ("(Twine cstring:\"hi\" empty)",
repr(Twine().concat(Twine("hi")))); repr(Twine().concat(Twine("hi"))));
EXPECT_EQ("(Twine smallstring:\"hi\" empty)",
repr(Twine().concat(Twine(SmallString<5>("hi")))));
EXPECT_EQ("(Twine smallstring:\"hey\" cstring:\"there\")",
repr(Twine(SmallString<7>("hey")).concat(Twine("there"))));
// Concatenation of unary ropes. // Concatenation of unary ropes.
EXPECT_EQ("(Twine cstring:\"a\" cstring:\"b\")", EXPECT_EQ("(Twine cstring:\"a\" cstring:\"b\")",
@@ -72,6 +77,8 @@ TEST(TwineTest, Concat) {
repr(Twine("a").concat(Twine("b")).concat(Twine("c")))); repr(Twine("a").concat(Twine("b")).concat(Twine("c"))));
EXPECT_EQ("(Twine cstring:\"a\" rope:(Twine cstring:\"b\" cstring:\"c\"))", EXPECT_EQ("(Twine cstring:\"a\" rope:(Twine cstring:\"b\" cstring:\"c\"))",
repr(Twine("a").concat(Twine("b").concat(Twine("c"))))); repr(Twine("a").concat(Twine("b").concat(Twine("c")))));
EXPECT_EQ("(Twine cstring:\"a\" rope:(Twine smallstring:\"b\" cstring:\"c\"))",
repr(Twine("a").concat(Twine(SmallString<3>("b")).concat(Twine("c")))));
} }
TEST(TwineTest, toNullTerminatedStringRef) { TEST(TwineTest, toNullTerminatedStringRef) {
@@ -79,6 +86,9 @@ TEST(TwineTest, toNullTerminatedStringRef) {
EXPECT_EQ(0, *Twine("hello").toNullTerminatedStringRef(storage).end()); EXPECT_EQ(0, *Twine("hello").toNullTerminatedStringRef(storage).end());
EXPECT_EQ(0, EXPECT_EQ(0,
*Twine(StringRef("hello")).toNullTerminatedStringRef(storage).end()); *Twine(StringRef("hello")).toNullTerminatedStringRef(storage).end());
EXPECT_EQ(0, *Twine(SmallString<11>("hello"))
.toNullTerminatedStringRef(storage)
.end());
} }
// I suppose linking in the entire code generator to add a unit test to check // I suppose linking in the entire code generator to add a unit test to check