aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/ADT/TinyPtrVector.h
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2012-09-05 22:31:59 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2012-09-05 22:31:59 -0700
commitcbbf0ced2c07892c0df3dd17def157ecb5e58b95 (patch)
treec1970fcebc736d4f731db0559a79a7ac5cb0f8bf /include/llvm/ADT/TinyPtrVector.h
parenta81c41dc02ccbc654a9c2f638f9fbf2b599f5dfd (diff)
parent31675153bd2d7617db8cb6aeb58054934c7b9f73 (diff)
downloadexternal_llvm-cbbf0ced2c07892c0df3dd17def157ecb5e58b95.zip
external_llvm-cbbf0ced2c07892c0df3dd17def157ecb5e58b95.tar.gz
external_llvm-cbbf0ced2c07892c0df3dd17def157ecb5e58b95.tar.bz2
am 31675153: Merge branch \'upstream\' into merge_2
* commit '31675153bd2d7617db8cb6aeb58054934c7b9f73': (542 commits) MaximumSpanningTree::EdgeWeightCompare: Make this comparator actually be a strict weak ordering, and don't pass possibly-null pointers to dyn_cast. Fix misaligned access in MachO object file reader: despite containing an int64_t, Symbol64TableEntry is actually only stored with 4-byte alignment within the file. Fix unaligned memory accesses when performing relocations in X86 JIT. There's no cost to using memcpy here: the fixed code is optimized by LLVM to perfect machine code. Don't pass a null pointer to cast<> in its unit tests. Don't bind a reference to a dereferenced null pointer (for return value of WeakVH::operator*). [ms-inline asm] Do not report a Parser error when matching inline assembly. Ignore the documentation-suggested location for compile_commands.json The presence of the empty file "foo" unfortunately does not improve LLVM in any way. Remove unnecessary cast that was also unnecessarily casting away constness. Provide a portability macro for __builtin_trap. Fix macros arguments with an underscore, dot or dollar in them. This is based on a patch by Andy/PaX. I added the support for dot and dollar. [ms-inline asm] Expose the ErrorInfo from the MatchInstructionImpl. In general, this is the index of the operand that failed to match. Formatting. No functional change. Make the wording in of the "expected identifier" error in the .macro directive consistent with the other "expected identifier" errors. Extracted from the Andy/PaX patch. I added the test. Pacify PVS-Studio by changing the type rather than doing a cast, a tweak suggested by David Blaikie. Add support for the --param ssp-buffer-size= driver option. PR9673 Use typedefs. Fix indentation. Extracted from the Andy/PaX patch. Remove unused variable. Extracted from the Andy/PaX patch. Fix typo. Extracted from the Andy/PaX patch. MCJIT: Tidy up the constructor. ...
Diffstat (limited to 'include/llvm/ADT/TinyPtrVector.h')
-rw-r--r--include/llvm/ADT/TinyPtrVector.h169
1 files changed, 134 insertions, 35 deletions
diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h
index 8f3925c..d3d33b8 100644
--- a/include/llvm/ADT/TinyPtrVector.h
+++ b/include/llvm/ADT/TinyPtrVector.h
@@ -11,8 +11,9 @@
#define LLVM_ADT_TINYPTRVECTOR_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
@@ -27,23 +28,78 @@ template <typename EltTy>
class TinyPtrVector {
public:
typedef llvm::SmallVector<EltTy, 4> VecTy;
+ typedef typename VecTy::value_type value_type;
+
llvm::PointerUnion<EltTy, VecTy*> Val;
-
+
TinyPtrVector() {}
+ ~TinyPtrVector() {
+ if (VecTy *V = Val.template dyn_cast<VecTy*>())
+ delete V;
+ }
+
TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
if (VecTy *V = Val.template dyn_cast<VecTy*>())
Val = new VecTy(*V);
}
+ TinyPtrVector &operator=(const TinyPtrVector &RHS) {
+ if (this == &RHS)
+ return *this;
+ if (RHS.empty()) {
+ this->clear();
+ return *this;
+ }
+
+ // Try to squeeze into the single slot. If it won't fit, allocate a copied
+ // vector.
+ if (Val.template is<EltTy>()) {
+ if (RHS.size() == 1)
+ Val = RHS.front();
+ else
+ Val = new VecTy(*RHS.Val.template get<VecTy*>());
+ return *this;
+ }
+
+ // If we have a full vector allocated, try to re-use it.
+ if (RHS.Val.template is<EltTy>()) {
+ Val.template get<VecTy*>()->clear();
+ Val.template get<VecTy*>()->push_back(RHS.front());
+ } else {
+ *Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>();
+ }
+ return *this;
+ }
+
#if LLVM_USE_RVALUE_REFERENCES
TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) {
RHS.Val = (EltTy)0;
}
-#endif
- ~TinyPtrVector() {
- if (VecTy *V = Val.template dyn_cast<VecTy*>())
+ TinyPtrVector &operator=(TinyPtrVector &&RHS) {
+ if (this == &RHS)
+ return *this;
+ if (RHS.empty()) {
+ this->clear();
+ return *this;
+ }
+
+ // If this vector has been allocated on the heap, re-use it if cheap. If it
+ // would require more copying, just delete it and we'll steal the other
+ // side.
+ if (VecTy *V = Val.template dyn_cast<VecTy*>()) {
+ if (RHS.Val.template is<EltTy>()) {
+ V->clear();
+ V->push_back(RHS.front());
+ return *this;
+ }
delete V;
+ }
+
+ Val = RHS.Val;
+ RHS.Val = (EltTy)0;
+ return *this;
}
-
+#endif
+
// implicit conversion operator to ArrayRef.
operator ArrayRef<EltTy>() const {
if (Val.isNull())
@@ -52,7 +108,7 @@ public:
return *Val.getAddrOfPtr1();
return *Val.template get<VecTy*>();
}
-
+
bool empty() const {
// This vector can be empty if it contains no element, or if it
// contains a pointer to an empty vector.
@@ -61,7 +117,7 @@ public:
return Vec->empty();
return false;
}
-
+
unsigned size() const {
if (empty())
return 0;
@@ -69,27 +125,21 @@ public:
return 1;
return Val.template get<VecTy*>()->size();
}
-
+
typedef const EltTy *const_iterator;
typedef EltTy *iterator;
iterator begin() {
- if (empty())
- return 0;
-
if (Val.template is<EltTy>())
return Val.getAddrOfPtr1();
-
+
return Val.template get<VecTy *>()->begin();
}
iterator end() {
- if (empty())
- return 0;
-
if (Val.template is<EltTy>())
- return begin() + 1;
-
+ return begin() + (Val.isNull() ? 0 : 1);
+
return Val.template get<VecTy *>()->end();
}
@@ -107,19 +157,19 @@ public:
assert(i == 0 && "tinyvector index out of range");
return V;
}
-
- assert(i < Val.template get<VecTy*>()->size() &&
+
+ assert(i < Val.template get<VecTy*>()->size() &&
"tinyvector index out of range");
return (*Val.template get<VecTy*>())[i];
}
-
+
EltTy front() const {
assert(!empty() && "vector empty");
if (EltTy V = Val.template dyn_cast<EltTy>())
return V;
return Val.template get<VecTy*>()->front();
}
-
+
EltTy back() const {
assert(!empty() && "vector empty");
if (EltTy V = Val.template dyn_cast<EltTy>())
@@ -127,26 +177,25 @@ public:
return Val.template get<VecTy*>()->back();
}
-
void push_back(EltTy NewVal) {
assert(NewVal != 0 && "Can't add a null value");
-
+
// If we have nothing, add something.
if (Val.isNull()) {
Val = NewVal;
return;
}
-
+
// If we have a single value, convert to a vector.
if (EltTy V = Val.template dyn_cast<EltTy>()) {
Val = new VecTy();
Val.template get<VecTy*>()->push_back(V);
}
-
+
// Add the new value, we know we have a vector.
Val.template get<VecTy*>()->push_back(NewVal);
}
-
+
void pop_back() {
// If we have a single value, convert to empty.
if (Val.template is<EltTy>())
@@ -155,7 +204,6 @@ public:
Vec->pop_back();
}
-
void clear() {
// If we have a single value, convert to empty.
if (Val.template is<EltTy>()) {
@@ -168,6 +216,9 @@ public:
}
iterator erase(iterator I) {
+ assert(I >= begin() && "Iterator to erase is out of bounds.");
+ assert(I < end() && "Erasing at past-the-end iterator.");
+
// If we have a single value, convert to empty.
if (Val.template is<EltTy>()) {
if (I == begin())
@@ -177,15 +228,63 @@ public:
// benefit to collapsing back to a pointer
return Vec->erase(I);
}
+ return end();
+ }
- return 0;
+ iterator erase(iterator S, iterator E) {
+ assert(S >= begin() && "Range to erase is out of bounds.");
+ assert(S <= E && "Trying to erase invalid range.");
+ assert(E <= end() && "Trying to erase past the end.");
+
+ if (Val.template is<EltTy>()) {
+ if (S == begin() && S != E)
+ Val = (EltTy)0;
+ } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
+ return Vec->erase(S, E);
+ }
+ return end();
+ }
+
+ iterator insert(iterator I, const EltTy &Elt) {
+ assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+ assert(I <= this->end() && "Inserting past the end of the vector.");
+ if (I == end()) {
+ push_back(Elt);
+ return llvm::prior(end());
+ }
+ assert(!Val.isNull() && "Null value with non-end insert iterator.");
+ if (EltTy V = Val.template dyn_cast<EltTy>()) {
+ assert(I == begin());
+ Val = Elt;
+ push_back(V);
+ return begin();
+ }
+
+ return Val.template get<VecTy*>()->insert(I, Elt);
+ }
+
+ template<typename ItTy>
+ iterator insert(iterator I, ItTy From, ItTy To) {
+ assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+ assert(I <= this->end() && "Inserting past the end of the vector.");
+ if (From == To)
+ return I;
+
+ // If we have a single value, convert to a vector.
+ ptrdiff_t Offset = I - begin();
+ if (Val.isNull()) {
+ if (llvm::next(From) == To) {
+ Val = *From;
+ return begin();
+ }
+
+ Val = new VecTy();
+ } else if (EltTy V = Val.template dyn_cast<EltTy>()) {
+ Val = new VecTy();
+ Val.template get<VecTy*>()->push_back(V);
+ }
+ return Val.template get<VecTy*>()->insert(begin() + Offset, From, To);
}
-
-private:
- void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
-#if LLVM_USE_RVALUE_REFERENCES
- void operator=(TinyPtrVector&&); // NOT IMPLEMENTED YET.
-#endif
};
} // end namespace llvm