Make readBytes pure virtual. Every real implementation has it.
[oota-llvm.git] / lib / Support / StreamableMemoryObject.cpp
1 //===- StreamableMemoryObject.cpp - Streamable data interface -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/Support/StreamableMemoryObject.h"
11 #include "llvm/Support/Compiler.h"
12 #include <cassert>
13 #include <cstddef>
14 #include <cstring>
15
16
17 using namespace llvm;
18
19 namespace {
20
21 class RawMemoryObject : public StreamableMemoryObject {
22 public:
23   RawMemoryObject(const unsigned char *Start, const unsigned char *End) :
24     FirstChar(Start), LastChar(End) {
25     assert(LastChar >= FirstChar && "Invalid start/end range");
26   }
27
28   uint64_t getExtent() const override {
29     return LastChar - FirstChar;
30   }
31   int readByte(uint64_t address, uint8_t* ptr) const override;
32   int readBytes(uint64_t address, uint64_t size,
33                 uint8_t *buf) const override;
34   const uint8_t *getPointer(uint64_t address, uint64_t size) const override;
35   bool isValidAddress(uint64_t address) const override {
36     return validAddress(address);
37   }
38   bool isObjectEnd(uint64_t address) const override {
39     return objectEnd(address);
40   }
41
42 private:
43   const uint8_t* const FirstChar;
44   const uint8_t* const LastChar;
45
46   // These are implemented as inline functions here to avoid multiple virtual
47   // calls per public function
48   bool validAddress(uint64_t address) const {
49     return static_cast<std::ptrdiff_t>(address) < LastChar - FirstChar;
50   }
51   bool objectEnd(uint64_t address) const {
52     return static_cast<std::ptrdiff_t>(address) == LastChar - FirstChar;
53   }
54
55   RawMemoryObject(const RawMemoryObject&) LLVM_DELETED_FUNCTION;
56   void operator=(const RawMemoryObject&) LLVM_DELETED_FUNCTION;
57 };
58
59 int RawMemoryObject::readByte(uint64_t address, uint8_t* ptr) const {
60   if (!validAddress(address)) return -1;
61   *ptr = *((uint8_t *)(uintptr_t)(address + FirstChar));
62   return 0;
63 }
64
65 int RawMemoryObject::readBytes(uint64_t address,
66                                uint64_t size,
67                                uint8_t *buf) const {
68   if (!validAddress(address) || !validAddress(address + size - 1)) return -1;
69   memcpy(buf, (uint8_t *)(uintptr_t)(address + FirstChar), size);
70   return size;
71 }
72
73 const uint8_t *RawMemoryObject::getPointer(uint64_t address,
74                                            uint64_t size) const {
75   return FirstChar + address;
76 }
77 } // anonymous namespace
78
79 namespace llvm {
80 // If the bitcode has a header, then its size is known, and we don't have to
81 // block until we actually want to read it.
82 bool StreamingMemoryObject::isValidAddress(uint64_t address) const {
83   if (ObjectSize && address < ObjectSize) return true;
84     return fetchToPos(address);
85 }
86
87 bool StreamingMemoryObject::isObjectEnd(uint64_t address) const {
88   if (ObjectSize) return address == ObjectSize;
89   fetchToPos(address);
90   return address == ObjectSize && address != 0;
91 }
92
93 uint64_t StreamingMemoryObject::getExtent() const {
94   if (ObjectSize) return ObjectSize;
95   size_t pos = BytesRead + kChunkSize;
96   // keep fetching until we run out of bytes
97   while (fetchToPos(pos)) pos += kChunkSize;
98   return ObjectSize;
99 }
100
101 int StreamingMemoryObject::readByte(uint64_t address, uint8_t* ptr) const {
102   if (!fetchToPos(address)) return -1;
103   *ptr = Bytes[address + BytesSkipped];
104   return 0;
105 }
106
107 int StreamingMemoryObject::readBytes(uint64_t address,
108                                      uint64_t size,
109                                      uint8_t *buf) const {
110   if (!fetchToPos(address + size - 1)) return -1;
111   memcpy(buf, &Bytes[address + BytesSkipped], size);
112   return 0;
113 }
114
115 bool StreamingMemoryObject::dropLeadingBytes(size_t s) {
116   if (BytesRead < s) return true;
117   BytesSkipped = s;
118   BytesRead -= s;
119   return false;
120 }
121
122 void StreamingMemoryObject::setKnownObjectSize(size_t size) {
123   ObjectSize = size;
124   Bytes.reserve(size);
125 }
126
127 StreamableMemoryObject *getNonStreamedMemoryObject(
128     const unsigned char *Start, const unsigned char *End) {
129   return new RawMemoryObject(Start, End);
130 }
131
132 StreamableMemoryObject::~StreamableMemoryObject() { }
133
134 StreamingMemoryObject::StreamingMemoryObject(DataStreamer *streamer) :
135   Bytes(kChunkSize), Streamer(streamer), BytesRead(0), BytesSkipped(0),
136   ObjectSize(0), EOFReached(false) {
137   BytesRead = streamer->GetBytes(&Bytes[0], kChunkSize);
138 }
139 }