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