aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Support
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-03 20:26:11 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-03 20:26:11 +0000
commit148779df305667b6942fee7e758fdf81a6498f38 (patch)
tree976d85fb9cb4bc8ed54348b045f742be90e10c57 /include/llvm/Support
parenta303c417bbdb53703c2c17398b08486bde78f1f6 (diff)
Diffstat (limited to 'include/llvm/Support')
-rw-r--r--include/llvm/Support/BinaryStreamArray.h234
-rw-r--r--include/llvm/Support/BinaryStreamReader.h28
-rw-r--r--include/llvm/Support/BinaryStreamRef.h3
-rw-r--r--include/llvm/Support/BinaryStreamWriter.h6
-rw-r--r--include/llvm/Support/DataExtractor.h22
-rw-r--r--include/llvm/Support/ELFRelocs/Hexagon.def5
6 files changed, 204 insertions, 94 deletions
diff --git a/include/llvm/Support/BinaryStreamArray.h b/include/llvm/Support/BinaryStreamArray.h
index 748a62be231e..f141c30f16c7 100644
--- a/include/llvm/Support/BinaryStreamArray.h
+++ b/include/llvm/Support/BinaryStreamArray.h
@@ -42,99 +42,34 @@ namespace llvm {
/// having to specify a second template argument to VarStreamArray (documented
/// below).
template <typename T> struct VarStreamArrayExtractor {
- typedef void Context;
+ struct ContextType {};
// Method intentionally deleted. You must provide an explicit specialization
- // with the following method implemented.
- static Error extract(BinaryStreamRef Stream, uint32_t &Len, T &Item,
- Context *Ctx) = delete;
-};
-
-/// VarStreamArray represents an array of variable length records backed by a
-/// stream. This could be a contiguous sequence of bytes in memory, it could
-/// be a file on disk, or it could be a PDB stream where bytes are stored as
-/// discontiguous blocks in a file. Usually it is desirable to treat arrays
-/// as contiguous blocks of memory, but doing so with large PDB files, for
-/// example, could mean allocating huge amounts of memory just to allow
-/// re-ordering of stream data to be contiguous before iterating over it. By
-/// abstracting this out, we need not duplicate this memory, and we can
-/// iterate over arrays in arbitrarily formatted streams. Elements are parsed
-/// lazily on iteration, so there is no upfront cost associated with building
-/// or copying a VarStreamArray, no matter how large it may be.
-///
-/// You create a VarStreamArray by specifying a ValueType and an Extractor type.
-/// If you do not specify an Extractor type, you are expected to specialize
-/// VarStreamArrayExtractor<T> for your ValueType.
-///
-/// The default extractor type is stateless, but by specializing
-/// VarStreamArrayExtractor or defining your own custom extractor type and
-/// adding the appropriate ContextType typedef to the class, you can pass a
-/// context field during construction of the VarStreamArray that will be
-/// passed to each call to extract.
-///
-template <typename ValueType, typename ExtractorType>
-class VarStreamArrayIterator;
-
-template <typename ValueType,
- typename ExtractorType = VarStreamArrayExtractor<ValueType>>
-class VarStreamArray {
-public:
- typedef typename ExtractorType::ContextType ContextType;
- typedef VarStreamArrayIterator<ValueType, ExtractorType> Iterator;
- friend Iterator;
-
- VarStreamArray() = default;
-
- explicit VarStreamArray(BinaryStreamRef Stream,
- ContextType *Context = nullptr)
- : Stream(Stream), Context(Context) {}
-
- VarStreamArray(const VarStreamArray<ValueType, ExtractorType> &Other)
- : Stream(Other.Stream), Context(Other.Context) {}
-
- Iterator begin(bool *HadError = nullptr) const {
- if (empty())
- return end();
-
- return Iterator(*this, Context, HadError);
- }
-
- Iterator end() const { return Iterator(); }
-
- bool empty() const { return Stream.getLength() == 0; }
-
- /// \brief given an offset into the array's underlying stream, return an
- /// iterator to the record at that offset. This is considered unsafe
- /// since the behavior is undefined if \p Offset does not refer to the
- /// beginning of a valid record.
- Iterator at(uint32_t Offset) const {
- return Iterator(*this, Context, Stream.drop_front(Offset), nullptr);
- }
-
- BinaryStreamRef getUnderlyingStream() const { return Stream; }
+ // with one of the following two methods implemented.
+ static Error extract(BinaryStreamRef Stream, uint32_t &Len, T &Item) = delete;
-private:
- BinaryStreamRef Stream;
- ContextType *Context = nullptr;
+ static Error extract(BinaryStreamRef Stream, uint32_t &Len, T &Item,
+ const ContextType &Ctx) = delete;
};
-template <typename ValueType, typename ExtractorType>
+template <typename ArrayType, typename Value, typename Extractor,
+ typename WrappedCtx>
class VarStreamArrayIterator
: public iterator_facade_base<
- VarStreamArrayIterator<ValueType, ExtractorType>,
- std::forward_iterator_tag, ValueType> {
- typedef typename ExtractorType::ContextType ContextType;
- typedef VarStreamArrayIterator<ValueType, ExtractorType> IterType;
- typedef VarStreamArray<ValueType, ExtractorType> ArrayType;
+ VarStreamArrayIterator<ArrayType, Value, Extractor, WrappedCtx>,
+ std::forward_iterator_tag, Value> {
+ typedef VarStreamArrayIterator<ArrayType, Value, Extractor, WrappedCtx>
+ IterType;
public:
- VarStreamArrayIterator(const ArrayType &Array, ContextType *Context,
+ VarStreamArrayIterator() = default;
+ VarStreamArrayIterator(const ArrayType &Array, const WrappedCtx &Ctx,
BinaryStreamRef Stream, bool *HadError = nullptr)
- : IterRef(Stream), Context(Context), Array(&Array), HadError(HadError) {
+ : IterRef(Stream), Ctx(&Ctx), Array(&Array), HadError(HadError) {
if (IterRef.getLength() == 0)
moveToEnd();
else {
- auto EC = ExtractorType::extract(IterRef, ThisLen, ThisValue, Context);
+ auto EC = Ctx.template invoke<Extractor>(IterRef, ThisLen, ThisValue);
if (EC) {
consumeError(std::move(EC));
markError();
@@ -142,11 +77,13 @@ public:
}
}
- VarStreamArrayIterator(const ArrayType &Array, ContextType *Context,
+ VarStreamArrayIterator(const ArrayType &Array, const WrappedCtx &Ctx,
bool *HadError = nullptr)
- : VarStreamArrayIterator(Array, Context, Array.Stream, HadError) {}
+ : VarStreamArrayIterator(Array, Ctx, Array.Stream, HadError) {}
+
+ VarStreamArrayIterator(const WrappedCtx &Ctx) : Ctx(&Ctx) {}
+ VarStreamArrayIterator(const VarStreamArrayIterator &Other) = default;
- VarStreamArrayIterator() = default;
~VarStreamArrayIterator() = default;
bool operator==(const IterType &R) const {
@@ -164,12 +101,12 @@ public:
return false;
}
- const ValueType &operator*() const {
+ const Value &operator*() const {
assert(Array && !HasError);
return ThisValue;
}
- ValueType &operator*() {
+ Value &operator*() {
assert(Array && !HasError);
return ThisValue;
}
@@ -185,7 +122,7 @@ public:
moveToEnd();
} else {
// There is some data after the current record.
- auto EC = ExtractorType::extract(IterRef, ThisLen, ThisValue, Context);
+ auto EC = Ctx->template invoke<Extractor>(IterRef, ThisLen, ThisValue);
if (EC) {
consumeError(std::move(EC));
markError();
@@ -210,15 +147,136 @@ private:
*HadError = true;
}
- ValueType ThisValue;
+ Value ThisValue;
BinaryStreamRef IterRef;
- ContextType *Context{nullptr};
+ const WrappedCtx *Ctx{nullptr};
const ArrayType *Array{nullptr};
uint32_t ThisLen{0};
bool HasError{false};
bool *HadError{nullptr};
};
+template <typename T, typename Context> struct ContextWrapper {
+ ContextWrapper() = default;
+
+ explicit ContextWrapper(Context &&Ctx) : Ctx(Ctx) {}
+
+ template <typename Extractor>
+ Error invoke(BinaryStreamRef Stream, uint32_t &Len, T &Item) const {
+ return Extractor::extract(Stream, Len, Item, Ctx);
+ }
+
+ Context Ctx;
+};
+
+template <typename T> struct ContextWrapper<T, void> {
+ ContextWrapper() = default;
+
+ template <typename Extractor>
+ Error invoke(BinaryStreamRef Stream, uint32_t &Len, T &Item) const {
+ return Extractor::extract(Stream, Len, Item);
+ }
+};
+
+/// VarStreamArray represents an array of variable length records backed by a
+/// stream. This could be a contiguous sequence of bytes in memory, it could
+/// be a file on disk, or it could be a PDB stream where bytes are stored as
+/// discontiguous blocks in a file. Usually it is desirable to treat arrays
+/// as contiguous blocks of memory, but doing so with large PDB files, for
+/// example, could mean allocating huge amounts of memory just to allow
+/// re-ordering of stream data to be contiguous before iterating over it. By
+/// abstracting this out, we need not duplicate this memory, and we can
+/// iterate over arrays in arbitrarily formatted streams. Elements are parsed
+/// lazily on iteration, so there is no upfront cost associated with building
+/// or copying a VarStreamArray, no matter how large it may be.
+///
+/// You create a VarStreamArray by specifying a ValueType and an Extractor type.
+/// If you do not specify an Extractor type, you are expected to specialize
+/// VarStreamArrayExtractor<T> for your ValueType.
+///
+/// The default extractor type is stateless, but by specializing
+/// VarStreamArrayExtractor or defining your own custom extractor type and
+/// adding the appropriate ContextType typedef to the class, you can pass a
+/// context field during construction of the VarStreamArray that will be
+/// passed to each call to extract.
+///
+template <typename Value, typename Extractor, typename WrappedCtx>
+class VarStreamArrayBase {
+ typedef VarStreamArrayBase<Value, Extractor, WrappedCtx> MyType;
+
+public:
+ typedef VarStreamArrayIterator<MyType, Value, Extractor, WrappedCtx> Iterator;
+ friend Iterator;
+
+ VarStreamArrayBase() = default;
+
+ VarStreamArrayBase(BinaryStreamRef Stream, const WrappedCtx &Ctx)
+ : Stream(Stream), Ctx(Ctx) {}
+
+ VarStreamArrayBase(const MyType &Other)
+ : Stream(Other.Stream), Ctx(Other.Ctx) {}
+
+ Iterator begin(bool *HadError = nullptr) const {
+ if (empty())
+ return end();
+
+ return Iterator(*this, Ctx, Stream, HadError);
+ }
+
+ bool valid() const { return Stream.valid(); }
+
+ Iterator end() const { return Iterator(Ctx); }
+
+ bool empty() const { return Stream.getLength() == 0; }
+
+ /// \brief given an offset into the array's underlying stream, return an
+ /// iterator to the record at that offset. This is considered unsafe
+ /// since the behavior is undefined if \p Offset does not refer to the
+ /// beginning of a valid record.
+ Iterator at(uint32_t Offset) const {
+ return Iterator(*this, Ctx, Stream.drop_front(Offset), nullptr);
+ }
+
+ BinaryStreamRef getUnderlyingStream() const { return Stream; }
+
+private:
+ BinaryStreamRef Stream;
+ WrappedCtx Ctx;
+};
+
+template <typename Value, typename Extractor, typename Context>
+class VarStreamArrayImpl
+ : public VarStreamArrayBase<Value, Extractor,
+ ContextWrapper<Value, Context>> {
+ typedef ContextWrapper<Value, Context> WrappedContext;
+ typedef VarStreamArrayImpl<Value, Extractor, Context> MyType;
+ typedef VarStreamArrayBase<Value, Extractor, WrappedContext> BaseType;
+
+public:
+ typedef Context ContextType;
+
+ VarStreamArrayImpl() = default;
+ VarStreamArrayImpl(BinaryStreamRef Stream, Context &&Ctx)
+ : BaseType(Stream, WrappedContext(std::forward<Context>(Ctx))) {}
+};
+
+template <typename Value, typename Extractor>
+class VarStreamArrayImpl<Value, Extractor, void>
+ : public VarStreamArrayBase<Value, Extractor, ContextWrapper<Value, void>> {
+ typedef ContextWrapper<Value, void> WrappedContext;
+ typedef VarStreamArrayImpl<Value, Extractor, void> MyType;
+ typedef VarStreamArrayBase<Value, Extractor, WrappedContext> BaseType;
+
+public:
+ VarStreamArrayImpl() = default;
+ VarStreamArrayImpl(BinaryStreamRef Stream)
+ : BaseType(Stream, WrappedContext()) {}
+};
+
+template <typename Value, typename Extractor = VarStreamArrayExtractor<Value>>
+using VarStreamArray =
+ VarStreamArrayImpl<Value, Extractor, typename Extractor::ContextType>;
+
template <typename T> class FixedStreamArrayIterator;
/// FixedStreamArray is similar to VarStreamArray, except with each record
diff --git a/include/llvm/Support/BinaryStreamReader.h b/include/llvm/Support/BinaryStreamReader.h
index f30d82d81b25..77738077f5ff 100644
--- a/include/llvm/Support/BinaryStreamReader.h
+++ b/include/llvm/Support/BinaryStreamReader.h
@@ -31,6 +31,7 @@ namespace llvm {
/// are overridable.
class BinaryStreamReader {
public:
+ BinaryStreamReader() = default;
explicit BinaryStreamReader(BinaryStreamRef Stream);
virtual ~BinaryStreamReader() {}
@@ -172,13 +173,29 @@ public:
/// \returns a success error code if the data was successfully read, otherwise
/// returns an appropriate error code.
template <typename T, typename U>
- Error
- readArray(VarStreamArray<T, U> &Array, uint32_t Size,
- typename VarStreamArray<T, U>::ContextType *Context = nullptr) {
+ Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
BinaryStreamRef S;
if (auto EC = readStreamRef(S, Size))
return EC;
- Array = VarStreamArray<T, U>(S, Context);
+ Array = VarStreamArray<T, U>(S);
+ return Error::success();
+ }
+
+ /// Read a VarStreamArray of size \p Size bytes and store the result into
+ /// \p Array. Updates the stream's offset to point after the newly read
+ /// array. Never causes a copy (although iterating the elements of the
+ /// VarStreamArray may, depending upon the implementation of the underlying
+ /// stream).
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ template <typename T, typename U, typename ContextType>
+ Error readArray(VarStreamArray<T, U> &Array, uint32_t Size,
+ ContextType &&Context) {
+ BinaryStreamRef S;
+ if (auto EC = readStreamRef(S, Size))
+ return EC;
+ Array = VarStreamArray<T, U>(S, std::move(Context));
return Error::success();
}
@@ -227,6 +244,9 @@ public:
/// \returns the next byte in the stream.
uint8_t peek() const;
+ std::pair<BinaryStreamReader, BinaryStreamReader>
+ split(uint32_t Offset) const;
+
private:
BinaryStreamRef Stream;
uint32_t Offset;
diff --git a/include/llvm/Support/BinaryStreamRef.h b/include/llvm/Support/BinaryStreamRef.h
index 23ce02fd7ca4..465e724a6886 100644
--- a/include/llvm/Support/BinaryStreamRef.h
+++ b/include/llvm/Support/BinaryStreamRef.h
@@ -98,6 +98,9 @@ public:
BinaryStreamRef(BinaryStreamRef &S, uint32_t Offset,
uint32_t Length) = delete;
+ /// Check if a Stream is valid.
+ bool valid() const { return Stream != nullptr; }
+
/// Given an Offset into this StreamRef and a Size, return a reference to a
/// buffer owned by the stream.
///
diff --git a/include/llvm/Support/BinaryStreamWriter.h b/include/llvm/Support/BinaryStreamWriter.h
index 6734a797ccc4..1b61c32a2541 100644
--- a/include/llvm/Support/BinaryStreamWriter.h
+++ b/include/llvm/Support/BinaryStreamWriter.h
@@ -20,6 +20,7 @@
#include "llvm/Support/Error.h"
#include <cstdint>
#include <type_traits>
+#include <utility>
namespace llvm {
@@ -30,8 +31,6 @@ namespace llvm {
/// although no methods are overridable.
class BinaryStreamWriter {
public:
- // FIXME: We should be able to slice and drop_front etc on Writers / Readers.
-
BinaryStreamWriter() = default;
explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
virtual ~BinaryStreamWriter() {}
@@ -152,6 +151,9 @@ public:
return writeStreamRef(Array.getUnderlyingStream());
}
+ /// Splits the Writer into two Writers at a given offset.
+ std::pair<BinaryStreamWriter, BinaryStreamWriter> split(uint32_t Off) const;
+
void setOffset(uint32_t Off) { Offset = Off; }
uint32_t getOffset() const { return Offset; }
uint32_t getLength() const { return Stream.getLength(); }
diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h
index 2d1180c228e3..380b628fd95f 100644
--- a/include/llvm/Support/DataExtractor.h
+++ b/include/llvm/Support/DataExtractor.h
@@ -58,6 +58,28 @@ public:
/// NULL will be returned.
const char *getCStr(uint32_t *offset_ptr) const;
+ /// Extract a C string from \a *OffsetPtr.
+ ///
+ /// Returns a StringRef for the C String from the data at the offset
+ /// pointed to by \a OffsetPtr. A variable length NULL terminated C
+ /// string will be extracted and the \a OffsetPtr will be
+ /// updated with the offset of the byte that follows the NULL
+ /// terminator byte.
+ ///
+ /// \param[in,out] OffsetPtr
+ /// A pointer to an offset within the data that will be advanced
+ /// by the appropriate number of bytes if the value is extracted
+ /// correctly. If the offset is out of bounds or there are not
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// \return
+ /// A StringRef for the C string value in the data. If the offset
+ /// pointed to by \a OffsetPtr is out of bounds, or if the
+ /// offset plus the length of the C string is out of bounds,
+ /// a default-initialized StringRef will be returned.
+ StringRef getCStrRef(uint32_t *OffsetPtr) const;
+
/// Extract an unsigned integer of size \a byte_size from \a
/// *offset_ptr.
///
diff --git a/include/llvm/Support/ELFRelocs/Hexagon.def b/include/llvm/Support/ELFRelocs/Hexagon.def
index 74e1d405cebd..5021e2b26ce5 100644
--- a/include/llvm/Support/ELFRelocs/Hexagon.def
+++ b/include/llvm/Support/ELFRelocs/Hexagon.def
@@ -99,3 +99,8 @@ ELF_RELOC(R_HEX_LD_GOT_32_6_X, 91)
ELF_RELOC(R_HEX_LD_GOT_16_X, 92)
ELF_RELOC(R_HEX_LD_GOT_11_X, 93)
ELF_RELOC(R_HEX_23_REG, 94)
+ELF_RELOC(R_HEX_GD_PLT_B22_PCREL_X, 95)
+ELF_RELOC(R_HEX_GD_PLT_B32_PCREL_X, 96)
+ELF_RELOC(R_HEX_LD_PLT_B22_PCREL_X, 97)
+ELF_RELOC(R_HEX_LD_PLT_B32_PCREL_X, 98)
+ELF_RELOC(R_HEX_27_REG, 99)