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