1234285Sdim//===- StreamableMemoryObject.h - Streamable data interface -----*- C++ -*-===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim 10234285Sdim 11252723Sdim#ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H 12252723Sdim#define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H 13234285Sdim 14234285Sdim#include "llvm/ADT/OwningPtr.h" 15245431Sdim#include "llvm/Support/Compiler.h" 16252723Sdim#include "llvm/Support/DataStream.h" 17234285Sdim#include "llvm/Support/MemoryObject.h" 18234285Sdim#include <vector> 19234285Sdim 20234285Sdimnamespace llvm { 21234285Sdim 22234285Sdim/// StreamableMemoryObject - Interface to data which might be streamed. 23234285Sdim/// Streamability has 2 important implications/restrictions. First, the data 24234285Sdim/// might not yet exist in memory when the request is made. This just means 25234285Sdim/// that readByte/readBytes might have to block or do some work to get it. 26234285Sdim/// More significantly, the exact size of the object might not be known until 27234285Sdim/// it has all been fetched. This means that to return the right result, 28234285Sdim/// getExtent must also wait for all the data to arrive; therefore it should 29234285Sdim/// not be called on objects which are actually streamed (this would defeat 30234285Sdim/// the purpose of streaming). Instead, isValidAddress and isObjectEnd can be 31234285Sdim/// used to test addresses without knowing the exact size of the stream. 32234285Sdim/// Finally, getPointer can be used instead of readBytes to avoid extra copying. 33234285Sdimclass StreamableMemoryObject : public MemoryObject { 34234285Sdim public: 35234285Sdim /// Destructor - Override as necessary. 36234285Sdim virtual ~StreamableMemoryObject(); 37234285Sdim 38234285Sdim /// getBase - Returns the lowest valid address in the region. 39234285Sdim /// 40234285Sdim /// @result - The lowest valid address. 41263509Sdim virtual uint64_t getBase() const LLVM_OVERRIDE = 0; 42234285Sdim 43234285Sdim /// getExtent - Returns the size of the region in bytes. (The region is 44234285Sdim /// contiguous, so the highest valid address of the region 45234285Sdim /// is getBase() + getExtent() - 1). 46234285Sdim /// May block until all bytes in the stream have been read 47234285Sdim /// 48234285Sdim /// @result - The size of the region. 49263509Sdim virtual uint64_t getExtent() const LLVM_OVERRIDE = 0; 50234285Sdim 51234285Sdim /// readByte - Tries to read a single byte from the region. 52234285Sdim /// May block until (address - base) bytes have been read 53234285Sdim /// @param address - The address of the byte, in the same space as getBase(). 54234285Sdim /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL. 55234285Sdim /// @result - 0 if successful; -1 if not. Failure may be due to a 56234285Sdim /// bounds violation or an implementation-specific error. 57263509Sdim virtual int readByte(uint64_t address, uint8_t *ptr) const LLVM_OVERRIDE = 0; 58234285Sdim 59234285Sdim /// readBytes - Tries to read a contiguous range of bytes from the 60234285Sdim /// region, up to the end of the region. 61234285Sdim /// May block until (address - base + size) bytes have 62234285Sdim /// been read. Additionally, StreamableMemoryObjects will 63234285Sdim /// not do partial reads - if size bytes cannot be read, 64234285Sdim /// readBytes will fail. 65234285Sdim /// 66234285Sdim /// @param address - The address of the first byte, in the same space as 67234285Sdim /// getBase(). 68263509Sdim /// @param size - The number of bytes to copy. 69234285Sdim /// @param buf - A pointer to a buffer to be filled in. Must be non-NULL 70234285Sdim /// and large enough to hold size bytes. 71234285Sdim /// @result - 0 if successful; -1 if not. Failure may be due to a 72234285Sdim /// bounds violation or an implementation-specific error. 73234285Sdim virtual int readBytes(uint64_t address, 74234285Sdim uint64_t size, 75263509Sdim uint8_t *buf) const LLVM_OVERRIDE = 0; 76234285Sdim 77234285Sdim /// getPointer - Ensures that the requested data is in memory, and returns 78234285Sdim /// A pointer to it. More efficient than using readBytes if the 79234285Sdim /// data is already in memory. 80234285Sdim /// May block until (address - base + size) bytes have been read 81234285Sdim /// @param address - address of the byte, in the same space as getBase() 82234285Sdim /// @param size - amount of data that must be available on return 83234285Sdim /// @result - valid pointer to the requested data 84234285Sdim virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0; 85234285Sdim 86234285Sdim /// isValidAddress - Returns true if the address is within the object 87234285Sdim /// (i.e. between base and base + extent - 1 inclusive) 88234285Sdim /// May block until (address - base) bytes have been read 89234285Sdim /// @param address - address of the byte, in the same space as getBase() 90234285Sdim /// @result - true if the address may be read with readByte() 91234285Sdim virtual bool isValidAddress(uint64_t address) const = 0; 92234285Sdim 93234285Sdim /// isObjectEnd - Returns true if the address is one past the end of the 94234285Sdim /// object (i.e. if it is equal to base + extent) 95234285Sdim /// May block until (address - base) bytes have been read 96234285Sdim /// @param address - address of the byte, in the same space as getBase() 97234285Sdim /// @result - true if the address is equal to base + extent 98234285Sdim virtual bool isObjectEnd(uint64_t address) const = 0; 99234285Sdim}; 100234285Sdim 101234285Sdim/// StreamingMemoryObject - interface to data which is actually streamed from 102234285Sdim/// a DataStreamer. In addition to inherited members, it has the 103234285Sdim/// dropLeadingBytes and setKnownObjectSize methods which are not applicable 104234285Sdim/// to non-streamed objects. 105234285Sdimclass StreamingMemoryObject : public StreamableMemoryObject { 106234285Sdimpublic: 107234285Sdim StreamingMemoryObject(DataStreamer *streamer); 108245431Sdim virtual uint64_t getBase() const LLVM_OVERRIDE { return 0; } 109245431Sdim virtual uint64_t getExtent() const LLVM_OVERRIDE; 110263509Sdim virtual int readByte(uint64_t address, uint8_t *ptr) const LLVM_OVERRIDE; 111234285Sdim virtual int readBytes(uint64_t address, 112234285Sdim uint64_t size, 113263509Sdim uint8_t *buf) const LLVM_OVERRIDE; 114245431Sdim virtual const uint8_t *getPointer(uint64_t address, 115245431Sdim uint64_t size) const LLVM_OVERRIDE { 116234285Sdim // This could be fixed by ensuring the bytes are fetched and making a copy, 117234285Sdim // requiring that the bitcode size be known, or otherwise ensuring that 118234285Sdim // the memory doesn't go away/get reallocated, but it's 119234285Sdim // not currently necessary. Users that need the pointer don't stream. 120234285Sdim assert(0 && "getPointer in streaming memory objects not allowed"); 121234285Sdim return NULL; 122234285Sdim } 123245431Sdim virtual bool isValidAddress(uint64_t address) const LLVM_OVERRIDE; 124245431Sdim virtual bool isObjectEnd(uint64_t address) const LLVM_OVERRIDE; 125234285Sdim 126234285Sdim /// Drop s bytes from the front of the stream, pushing the positions of the 127234285Sdim /// remaining bytes down by s. This is used to skip past the bitcode header, 128234285Sdim /// since we don't know a priori if it's present, and we can't put bytes 129234285Sdim /// back into the stream once we've read them. 130234285Sdim bool dropLeadingBytes(size_t s); 131234285Sdim 132234285Sdim /// If the data object size is known in advance, many of the operations can 133234285Sdim /// be made more efficient, so this method should be called before reading 134234285Sdim /// starts (although it can be called anytime). 135234285Sdim void setKnownObjectSize(size_t size); 136234285Sdim 137234285Sdimprivate: 138234285Sdim const static uint32_t kChunkSize = 4096 * 4; 139234285Sdim mutable std::vector<unsigned char> Bytes; 140234285Sdim OwningPtr<DataStreamer> Streamer; 141234285Sdim mutable size_t BytesRead; // Bytes read from stream 142234285Sdim size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header) 143234285Sdim mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached 144234285Sdim mutable bool EOFReached; 145234285Sdim 146234285Sdim // Fetch enough bytes such that Pos can be read or EOF is reached 147234285Sdim // (i.e. BytesRead > Pos). Return true if Pos can be read. 148234285Sdim // Unlike most of the functions in BitcodeReader, returns true on success. 149234285Sdim // Most of the requests will be small, but we fetch at kChunkSize bytes 150234285Sdim // at a time to avoid making too many potentially expensive GetBytes calls 151234285Sdim bool fetchToPos(size_t Pos) const { 152234285Sdim if (EOFReached) return Pos < ObjectSize; 153234285Sdim while (Pos >= BytesRead) { 154234285Sdim Bytes.resize(BytesRead + BytesSkipped + kChunkSize); 155234285Sdim size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped], 156234285Sdim kChunkSize); 157234285Sdim BytesRead += bytes; 158234285Sdim if (bytes < kChunkSize) { 159234285Sdim if (ObjectSize && BytesRead < Pos) 160234285Sdim assert(0 && "Unexpected short read fetching bitcode"); 161234285Sdim if (BytesRead <= Pos) { // reached EOF/ran out of bytes 162234285Sdim ObjectSize = BytesRead; 163234285Sdim EOFReached = true; 164234285Sdim return false; 165234285Sdim } 166234285Sdim } 167234285Sdim } 168234285Sdim return true; 169234285Sdim } 170234285Sdim 171245431Sdim StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; 172245431Sdim void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; 173234285Sdim}; 174234285Sdim 175234285SdimStreamableMemoryObject *getNonStreamedMemoryObject( 176234285Sdim const unsigned char *Start, const unsigned char *End); 177234285Sdim 178234285Sdim} 179234285Sdim#endif // STREAMABLEMEMORYOBJECT_H_ 180