1 //===- StreamableMemoryObject.h - Streamable data interface -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H
12 #define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H
14 #include "llvm/Support/Compiler.h"
15 #include "llvm/Support/DataStream.h"
16 #include "llvm/Support/ErrorHandling.h"
17 #include "llvm/Support/MemoryObject.h"
24 /// Interface to data which might be streamed. Streamability has 2 important
25 /// implications/restrictions. First, the data might not yet exist in memory
26 /// when the request is made. This just means that readByte/readBytes might have
27 /// to block or do some work to get it. More significantly, the exact size of
28 /// the object might not be known until it has all been fetched. This means that
29 /// to return the right result, getExtent must also wait for all the data to
30 /// arrive; therefore it should not be called on objects which are actually
31 /// streamed (this would defeat the purpose of streaming). Instead,
32 /// isValidAddress and isObjectEnd can be used to test addresses without knowing
33 /// the exact size of the stream. Finally, getPointer can be used instead of
34 /// readBytes to avoid extra copying.
35 class StreamableMemoryObject : public MemoryObject {
37 virtual ~StreamableMemoryObject();
39 /// Ensures that the requested data is in memory, and returns a pointer to it.
40 /// More efficient than using readBytes if the data is already in memory. May
41 /// block until (address - base + size) bytes have been read
42 /// @param address - address of the byte, in the same space as getBase()
43 /// @param size - amount of data that must be available on return
44 /// @result - valid pointer to the requested data
45 virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0;
47 /// Returns true if the address is within the object (i.e. between base and
48 /// base + extent - 1 inclusive). May block until (address - base) bytes have
50 /// @param address - address of the byte, in the same space as getBase()
51 /// @result - true if the address may be read with readByte()
52 virtual bool isValidAddress(uint64_t address) const = 0;
54 /// Returns true if the address is one past the end of the object (i.e. if it
55 /// is equal to base + extent). May block until (address - base) bytes have
57 /// @param address - address of the byte, in the same space as getBase()
58 /// @result - true if the address is equal to base + extent
59 virtual bool isObjectEnd(uint64_t address) const = 0;
62 /// Interface to data which is actually streamed from a DataStreamer. In
63 /// addition to inherited members, it has the dropLeadingBytes and
64 /// setKnownObjectSize methods which are not applicable to non-streamed objects.
65 class StreamingMemoryObject : public StreamableMemoryObject {
67 StreamingMemoryObject(DataStreamer *streamer);
68 uint64_t getExtent() const override;
69 int readBytes(uint64_t address, uint64_t size,
70 uint8_t *buf) const override;
71 const uint8_t *getPointer(uint64_t address, uint64_t size) const override {
72 // This could be fixed by ensuring the bytes are fetched and making a copy,
73 // requiring that the bitcode size be known, or otherwise ensuring that
74 // the memory doesn't go away/get reallocated, but it's
75 // not currently necessary. Users that need the pointer don't stream.
76 llvm_unreachable("getPointer in streaming memory objects not allowed");
79 bool isValidAddress(uint64_t address) const override;
80 bool isObjectEnd(uint64_t address) const override;
82 /// Drop s bytes from the front of the stream, pushing the positions of the
83 /// remaining bytes down by s. This is used to skip past the bitcode header,
84 /// since we don't know a priori if it's present, and we can't put bytes
85 /// back into the stream once we've read them.
86 bool dropLeadingBytes(size_t s);
88 /// If the data object size is known in advance, many of the operations can
89 /// be made more efficient, so this method should be called before reading
90 /// starts (although it can be called anytime).
91 void setKnownObjectSize(size_t size);
94 const static uint32_t kChunkSize = 4096 * 4;
95 mutable std::vector<unsigned char> Bytes;
96 std::unique_ptr<DataStreamer> Streamer;
97 mutable size_t BytesRead; // Bytes read from stream
98 size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header)
99 mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached
100 mutable bool EOFReached;
102 // Fetch enough bytes such that Pos can be read or EOF is reached
103 // (i.e. BytesRead > Pos). Return true if Pos can be read.
104 // Unlike most of the functions in BitcodeReader, returns true on success.
105 // Most of the requests will be small, but we fetch at kChunkSize bytes
106 // at a time to avoid making too many potentially expensive GetBytes calls
107 bool fetchToPos(size_t Pos) const {
108 if (EOFReached) return Pos < ObjectSize;
109 while (Pos >= BytesRead) {
110 Bytes.resize(BytesRead + BytesSkipped + kChunkSize);
111 size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped],
114 if (bytes < kChunkSize) {
115 assert((!ObjectSize || BytesRead >= Pos) &&
116 "Unexpected short read fetching bitcode");
117 if (BytesRead <= Pos) { // reached EOF/ran out of bytes
118 ObjectSize = BytesRead;
127 StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
128 void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION;
131 StreamableMemoryObject *getNonStreamedMemoryObject(
132 const unsigned char *Start, const unsigned char *End);
135 #endif // STREAMABLEMEMORYOBJECT_H_