[llvm-commits] [llvm] r135365 - in /llvm/trunk: docs/ProgrammersManual.html include/llvm/ADT/TinyPtrVector.h

Frits van Bommel fvbommel at gmail.com
Mon Jul 18 01:25:00 PDT 2011


On 18 July 2011 03:40, Chris Lattner <sabre at nondot.org> wrote:
> Added: llvm/trunk/include/llvm/ADT/TinyPtrVector.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/TinyPtrVector.h?rev=135365&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/TinyPtrVector.h (added)
> +++ llvm/trunk/include/llvm/ADT/TinyPtrVector.h Sun Jul 17 20:40:02 2011
> @@ -0,0 +1,115 @@
> +//===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file defines the Type class.

s/Type/TinyPtrVector/

> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_ADT_TINYPTRVECTOR_H
> +#define LLVM_ADT_TINYPTRVECTOR_H
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/PointerUnion.h"
> +
> +namespace llvm {
> +
> +/// TinyPtrVector - This class is specialized for cases where there are
> +/// normally 0 or 1 element in a vector, but is general enough to go beyond that
> +/// when required.
> +///
> +/// NOTE: This container doesn't allow you to store a null pointer into it.

This restriction could be lifted by using a null VecTy* as the empty
value instead of any null pointer (what empty() currently checks for)
or a null EltTy (what can actually happen).
Several changes would need to be made:
 * Swapping the ordering in the PointerUnion (so that default
construction still makes it empty) or just explicitly initializing Val
to (VecTy*)0.
 * The biggest change: reimplementing empty() as:
  bool empty() const {
    if (Val.template is<EltTy>())
      return Val.template get<EltTy>();
    if (VecTy *Vec = Val.template get<VecTy*>()
      return Vec->empty();
    return false;
  }
 * assigning (VectTy*)0 in the single-element case in clear().
 * Using empty() to check for emptyness instead of Val.isNull() in operator[].
 * Obviously, removing the assert that it's not null at the top of push_back().
 * Using 'Val.isNull() && Val.template is<VecTy*>()' instead of just
'Val.isNull()' in push_back() to check for 'no elements and no
vector'. '!Val.getOpaqueValue()' would work too, if you swapped the
element types of the PointerUnion as suggested above, but looks more
fragile. Or maybe something nicer I haven't thought of.
 * Using is<EltTy> and get<EltTy> instead of dyn_cast<EltTy> in a few
places because the dyn_cast can now return null even if there *is* an
element but it happens to be null.
 * Anything I missed (?).

But if none of the use cases you have in mind for this require it this
might not be worth the added complexity.

> +///
> +template <typename EltTy>
> +class TinyPtrVector {
> +public:
> +  typedef llvm::SmallVector<EltTy, 4> VecTy;
> +  llvm::PointerUnion<EltTy, VecTy*> Val;
> +
> +  TinyPtrVector() {}
> +  TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
> +    if (VecTy *V = Val.template dyn_cast<VecTy*>())
> +      Val = new VecTy(*V);
> +  }
> +  ~TinyPtrVector() {
> +    if (VecTy *V = Val.template dyn_cast<VecTy*>())
> +      delete V;
> +  }
> +
> +  /// empty() - This vector can be empty if it contains no element, or if it
> +  /// contains a pointer to an empty vector.

This doesn't seem doc-comment worthy. It talks about implementation
details the user shouldn't care about and which aren't mentioned in
any of the other documentation.
All other comments of this kind are inside the methods, which is where
this one belongs too.

> +  bool empty() const {
> +    if (Val.isNull()) return true;
> +    if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
> +      return Vec->empty();
> +    return false;
> +  }
> +
> +  unsigned size() const {
> +    if (empty())
> +      return 0;
> +    if (Val. template is<EltTy>())

There's an extra space before 'template', which doesn't match the
style used in most other cases in this file.

> +      return 1;
> +    return Val. template get<VecTy*>()->size();

Ditto.

> +  }
> +
> +  EltTy operator[](unsigned i) const {
> +    assert(!Val.isNull() && "can't index into an empty vector");
> +    if (EltTy V = Val.template dyn_cast<EltTy>()) {
> +      assert(i == 0 && "tinyvector index out of range");
> +      return V;
> +    }
> +
> +    assert(i < Val. template get<VecTy*>()->size() &&

Ditto.

> +           "tinyvector index out of range");
> +    return (*Val. template get<VecTy*>())[i];

Ditto.

> +  }
> +
> +  EltTy front() const {
> +    assert(!empty() && "vector empty");
> +    if (EltTy V = Val.template dyn_cast<EltTy>())
> +      return V;
> +    return Val.template get<VecTy*>()->front();
> +  }
> +
> +  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>()) {

There are two spaces in 'template  dyn_cast'.

> +      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 clear() {
> +    // If we have a single value, convert to empty.
> +    if (EltTy V = Val.template dyn_cast<EltTy>()) {
> +      Val = (EltTy)0;
> +    } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
> +      // If we have a vector form, just clear it.
> +      Vec->clear();
> +    }
> +    // Otherwise, we're already empty.
> +  }
> +
> +private:
> +  void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
> +};
> +} // end namespace llvm
> +
> +#endif




More information about the llvm-commits mailing list