2009-07-24 07:04:27 +00:00
|
|
|
//===-- Twine.cpp - Fast Temporary String Concatenation -------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2009-08-19 18:09:47 +00:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2010-01-05 01:28:40 +00:00
|
|
|
#include "llvm/Support/Debug.h"
|
2009-07-24 07:04:27 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
std::string Twine::str() const {
|
2011-07-15 11:05:37 +00:00
|
|
|
// If we're storing only a std::string, just return it.
|
|
|
|
if (LHSKind == StdStringKind && RHSKind == EmptyKind)
|
|
|
|
return *static_cast<const std::string*>(LHS);
|
|
|
|
|
|
|
|
// Otherwise, flatten and copy the contents first.
|
2009-08-19 18:09:47 +00:00
|
|
|
SmallString<256> Vec;
|
2010-01-13 12:45:23 +00:00
|
|
|
return toStringRef(Vec).str();
|
2009-07-24 07:04:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Twine::toVector(SmallVectorImpl<char> &Out) const {
|
|
|
|
raw_svector_ostream OS(Out);
|
|
|
|
print(OS);
|
|
|
|
}
|
|
|
|
|
2010-01-13 12:45:23 +00:00
|
|
|
StringRef Twine::toStringRef(SmallVectorImpl<char> &Out) const {
|
|
|
|
if (isSingleStringRef())
|
|
|
|
return getSingleStringRef();
|
|
|
|
toVector(Out);
|
|
|
|
return StringRef(Out.data(), Out.size());
|
|
|
|
}
|
|
|
|
|
2010-12-01 20:37:30 +00:00
|
|
|
StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
|
2010-12-03 05:42:25 +00:00
|
|
|
if (isUnary()) {
|
|
|
|
switch (getLHSKind()) {
|
|
|
|
case CStringKind:
|
|
|
|
// Already null terminated, yay!
|
|
|
|
return StringRef(static_cast<const char*>(LHS));
|
|
|
|
case StdStringKind: {
|
2011-07-15 11:05:37 +00:00
|
|
|
const std::string *str = static_cast<const std::string*>(LHS);
|
|
|
|
return StringRef(str->c_str(), str->size());
|
|
|
|
}
|
2010-12-03 05:42:25 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2010-12-01 20:37:30 +00:00
|
|
|
}
|
|
|
|
toVector(Out);
|
|
|
|
Out.push_back(0);
|
|
|
|
Out.pop_back();
|
|
|
|
return StringRef(Out.data(), Out.size());
|
|
|
|
}
|
|
|
|
|
2010-11-26 04:16:08 +00:00
|
|
|
void Twine::printOneChild(raw_ostream &OS, const void *Ptr,
|
2009-07-24 07:04:27 +00:00
|
|
|
NodeKind Kind) const {
|
|
|
|
switch (Kind) {
|
|
|
|
case Twine::NullKind: break;
|
|
|
|
case Twine::EmptyKind: break;
|
2009-07-29 07:08:44 +00:00
|
|
|
case Twine::TwineKind:
|
2010-11-26 04:16:08 +00:00
|
|
|
static_cast<const Twine*>(Ptr)->print(OS);
|
2009-07-29 07:08:44 +00:00
|
|
|
break;
|
2010-11-26 04:16:08 +00:00
|
|
|
case Twine::CStringKind:
|
|
|
|
OS << static_cast<const char*>(Ptr);
|
2009-07-24 07:04:27 +00:00
|
|
|
break;
|
|
|
|
case Twine::StdStringKind:
|
2010-11-26 04:16:08 +00:00
|
|
|
OS << *static_cast<const std::string*>(Ptr);
|
2009-07-24 07:04:27 +00:00
|
|
|
break;
|
|
|
|
case Twine::StringRefKind:
|
2010-11-26 04:16:08 +00:00
|
|
|
OS << *static_cast<const StringRef*>(Ptr);
|
2009-07-24 07:04:27 +00:00
|
|
|
break;
|
2009-07-30 21:15:14 +00:00
|
|
|
case Twine::DecUIKind:
|
Implement rdar://7415680 - Twine integer support lacks greatness
Microoptimize Twine's with unsigned and int to not pin their value to
the stack. This saves stack space in common cases and allows mem2reg
in the caller. A simple example is:
void foo(const Twine &);
void bar(int x) {
foo("xyz: " + Twine(x));
}
Before:
__Z3bari:
subq $40, %rsp
movl %edi, 36(%rsp)
leaq L_.str3(%rip), %rax
leaq 36(%rsp), %rcx
leaq 8(%rsp), %rdi
movq %rax, 8(%rsp)
movq %rcx, 16(%rsp)
movb $3, 24(%rsp)
movb $7, 25(%rsp)
callq __Z3fooRKN4llvm5TwineE
addq $40, %rsp
ret
After:
__Z3bari:
subq $24, %rsp
leaq L_.str3(%rip), %rax
movq %rax, (%rsp)
movslq %edi, %rax
movq %rax, 8(%rsp)
movb $3, 16(%rsp)
movb $7, 17(%rsp)
leaq (%rsp), %rdi
callq __Z3fooRKN4llvm5TwineE
addq $24, %rsp
ret
It saves 16 bytes of stack and one instruction in this case.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103107 91177308-0d34-0410-b5e6-96231b3b80d8
2010-05-05 18:40:33 +00:00
|
|
|
OS << (unsigned)(uintptr_t)Ptr;
|
2009-07-30 03:47:15 +00:00
|
|
|
break;
|
2009-07-30 21:15:14 +00:00
|
|
|
case Twine::DecIKind:
|
Implement rdar://7415680 - Twine integer support lacks greatness
Microoptimize Twine's with unsigned and int to not pin their value to
the stack. This saves stack space in common cases and allows mem2reg
in the caller. A simple example is:
void foo(const Twine &);
void bar(int x) {
foo("xyz: " + Twine(x));
}
Before:
__Z3bari:
subq $40, %rsp
movl %edi, 36(%rsp)
leaq L_.str3(%rip), %rax
leaq 36(%rsp), %rcx
leaq 8(%rsp), %rdi
movq %rax, 8(%rsp)
movq %rcx, 16(%rsp)
movb $3, 24(%rsp)
movb $7, 25(%rsp)
callq __Z3fooRKN4llvm5TwineE
addq $40, %rsp
ret
After:
__Z3bari:
subq $24, %rsp
leaq L_.str3(%rip), %rax
movq %rax, (%rsp)
movslq %edi, %rax
movq %rax, 8(%rsp)
movb $3, 16(%rsp)
movb $7, 17(%rsp)
leaq (%rsp), %rdi
callq __Z3fooRKN4llvm5TwineE
addq $24, %rsp
ret
It saves 16 bytes of stack and one instruction in this case.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103107 91177308-0d34-0410-b5e6-96231b3b80d8
2010-05-05 18:40:33 +00:00
|
|
|
OS << (int)(intptr_t)Ptr;
|
2009-07-30 03:47:15 +00:00
|
|
|
break;
|
2009-07-30 21:15:14 +00:00
|
|
|
case Twine::DecULKind:
|
|
|
|
OS << *static_cast<const unsigned long*>(Ptr);
|
2009-07-29 07:08:44 +00:00
|
|
|
break;
|
2009-07-30 21:15:14 +00:00
|
|
|
case Twine::DecLKind:
|
|
|
|
OS << *static_cast<const long*>(Ptr);
|
|
|
|
break;
|
|
|
|
case Twine::DecULLKind:
|
|
|
|
OS << *static_cast<const unsigned long long*>(Ptr);
|
|
|
|
break;
|
|
|
|
case Twine::DecLLKind:
|
|
|
|
OS << *static_cast<const long long*>(Ptr);
|
2009-07-29 07:08:44 +00:00
|
|
|
break;
|
|
|
|
case Twine::UHexKind:
|
2009-07-30 18:30:19 +00:00
|
|
|
OS.write_hex(*static_cast<const uint64_t*>(Ptr));
|
2009-07-24 07:04:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-26 04:16:08 +00:00
|
|
|
void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr,
|
2009-07-24 07:04:27 +00:00
|
|
|
NodeKind Kind) const {
|
|
|
|
switch (Kind) {
|
|
|
|
case Twine::NullKind:
|
|
|
|
OS << "null"; break;
|
|
|
|
case Twine::EmptyKind:
|
|
|
|
OS << "empty"; break;
|
2009-07-29 07:08:44 +00:00
|
|
|
case Twine::TwineKind:
|
|
|
|
OS << "rope:";
|
|
|
|
static_cast<const Twine*>(Ptr)->printRepr(OS);
|
|
|
|
break;
|
2009-07-24 07:04:27 +00:00
|
|
|
case Twine::CStringKind:
|
2009-07-29 07:08:44 +00:00
|
|
|
OS << "cstring:\""
|
|
|
|
<< static_cast<const char*>(Ptr) << "\"";
|
2009-07-24 07:04:27 +00:00
|
|
|
break;
|
|
|
|
case Twine::StdStringKind:
|
2009-07-29 07:08:44 +00:00
|
|
|
OS << "std::string:\""
|
|
|
|
<< static_cast<const std::string*>(Ptr) << "\"";
|
2009-07-24 07:04:27 +00:00
|
|
|
break;
|
|
|
|
case Twine::StringRefKind:
|
2009-07-29 07:08:44 +00:00
|
|
|
OS << "stringref:\""
|
|
|
|
<< static_cast<const StringRef*>(Ptr) << "\"";
|
2009-07-24 07:04:27 +00:00
|
|
|
break;
|
2009-07-30 21:15:14 +00:00
|
|
|
case Twine::DecUIKind:
|
Implement rdar://7415680 - Twine integer support lacks greatness
Microoptimize Twine's with unsigned and int to not pin their value to
the stack. This saves stack space in common cases and allows mem2reg
in the caller. A simple example is:
void foo(const Twine &);
void bar(int x) {
foo("xyz: " + Twine(x));
}
Before:
__Z3bari:
subq $40, %rsp
movl %edi, 36(%rsp)
leaq L_.str3(%rip), %rax
leaq 36(%rsp), %rcx
leaq 8(%rsp), %rdi
movq %rax, 8(%rsp)
movq %rcx, 16(%rsp)
movb $3, 24(%rsp)
movb $7, 25(%rsp)
callq __Z3fooRKN4llvm5TwineE
addq $40, %rsp
ret
After:
__Z3bari:
subq $24, %rsp
leaq L_.str3(%rip), %rax
movq %rax, (%rsp)
movslq %edi, %rax
movq %rax, 8(%rsp)
movb $3, 16(%rsp)
movb $7, 17(%rsp)
leaq (%rsp), %rdi
callq __Z3fooRKN4llvm5TwineE
addq $24, %rsp
ret
It saves 16 bytes of stack and one instruction in this case.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103107 91177308-0d34-0410-b5e6-96231b3b80d8
2010-05-05 18:40:33 +00:00
|
|
|
OS << "decUI:\"" << (unsigned)(uintptr_t)Ptr << "\"";
|
2009-07-30 21:15:14 +00:00
|
|
|
break;
|
|
|
|
case Twine::DecIKind:
|
Implement rdar://7415680 - Twine integer support lacks greatness
Microoptimize Twine's with unsigned and int to not pin their value to
the stack. This saves stack space in common cases and allows mem2reg
in the caller. A simple example is:
void foo(const Twine &);
void bar(int x) {
foo("xyz: " + Twine(x));
}
Before:
__Z3bari:
subq $40, %rsp
movl %edi, 36(%rsp)
leaq L_.str3(%rip), %rax
leaq 36(%rsp), %rcx
leaq 8(%rsp), %rdi
movq %rax, 8(%rsp)
movq %rcx, 16(%rsp)
movb $3, 24(%rsp)
movb $7, 25(%rsp)
callq __Z3fooRKN4llvm5TwineE
addq $40, %rsp
ret
After:
__Z3bari:
subq $24, %rsp
leaq L_.str3(%rip), %rax
movq %rax, (%rsp)
movslq %edi, %rax
movq %rax, 8(%rsp)
movb $3, 16(%rsp)
movb $7, 17(%rsp)
leaq (%rsp), %rdi
callq __Z3fooRKN4llvm5TwineE
addq $24, %rsp
ret
It saves 16 bytes of stack and one instruction in this case.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103107 91177308-0d34-0410-b5e6-96231b3b80d8
2010-05-05 18:40:33 +00:00
|
|
|
OS << "decI:\"" << (int)(intptr_t)Ptr << "\"";
|
2009-07-30 21:15:14 +00:00
|
|
|
break;
|
|
|
|
case Twine::DecULKind:
|
|
|
|
OS << "decUL:\"" << *static_cast<const unsigned long*>(Ptr) << "\"";
|
2009-07-30 03:47:15 +00:00
|
|
|
break;
|
2009-07-30 21:15:14 +00:00
|
|
|
case Twine::DecLKind:
|
|
|
|
OS << "decL:\"" << *static_cast<const long*>(Ptr) << "\"";
|
2009-07-30 03:47:15 +00:00
|
|
|
break;
|
2009-07-30 21:15:14 +00:00
|
|
|
case Twine::DecULLKind:
|
|
|
|
OS << "decULL:\"" << *static_cast<const unsigned long long*>(Ptr) << "\"";
|
2009-07-29 07:08:44 +00:00
|
|
|
break;
|
2009-07-30 21:15:14 +00:00
|
|
|
case Twine::DecLLKind:
|
|
|
|
OS << "decLL:\"" << *static_cast<const long long*>(Ptr) << "\"";
|
2009-07-29 07:08:44 +00:00
|
|
|
break;
|
|
|
|
case Twine::UHexKind:
|
2009-07-30 21:15:14 +00:00
|
|
|
OS << "uhex:\"" << static_cast<const uint64_t*>(Ptr) << "\"";
|
2009-07-24 07:04:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Twine::print(raw_ostream &OS) const {
|
|
|
|
printOneChild(OS, LHS, getLHSKind());
|
|
|
|
printOneChild(OS, RHS, getRHSKind());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Twine::printRepr(raw_ostream &OS) const {
|
|
|
|
OS << "(Twine ";
|
|
|
|
printOneChildRepr(OS, LHS, getLHSKind());
|
|
|
|
OS << " ";
|
|
|
|
printOneChildRepr(OS, RHS, getRHSKind());
|
|
|
|
OS << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Twine::dump() const {
|
2010-01-05 01:28:40 +00:00
|
|
|
print(llvm::dbgs());
|
2009-07-24 07:04:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Twine::dumpRepr() const {
|
2010-01-05 01:28:40 +00:00
|
|
|
printRepr(llvm::dbgs());
|
2009-07-24 07:04:27 +00:00
|
|
|
}
|