144ebf8b0331cb3a994a8df16fb63fdcdbc37d927Nick Lewycky//===- StreamableMemoryObject.h - Streamable data interface -----*- C++ -*-===// 22ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// 32ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// The LLVM Compiler Infrastructure 42ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// 52ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// This file is distributed under the University of Illinois Open Source 62ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// License. See LICENSE.TXT for details. 72ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// 82ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff//===----------------------------------------------------------------------===// 92ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 102ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 11674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H 12674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H 132ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 14f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper#include "llvm/Support/Compiler.h" 152ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include "llvm/Support/DataStream.h" 16cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/ErrorHandling.h" 17255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include "llvm/Support/MemoryObject.h" 1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <cassert> 1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include <memory> 202ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include <vector> 212ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 222ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffnamespace llvm { 232ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 242ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// StreamableMemoryObject - Interface to data which might be streamed. 252ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// Streamability has 2 important implications/restrictions. First, the data 262ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// might not yet exist in memory when the request is made. This just means 272ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// that readByte/readBytes might have to block or do some work to get it. 282ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// More significantly, the exact size of the object might not be known until 292ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// it has all been fetched. This means that to return the right result, 302ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// getExtent must also wait for all the data to arrive; therefore it should 312ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// not be called on objects which are actually streamed (this would defeat 322ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// the purpose of streaming). Instead, isValidAddress and isObjectEnd can be 332ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// used to test addresses without knowing the exact size of the stream. 342ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// Finally, getPointer can be used instead of readBytes to avoid extra copying. 352ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffclass StreamableMemoryObject : public MemoryObject { 362ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff public: 372ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// Destructor - Override as necessary. 382ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff virtual ~StreamableMemoryObject(); 392ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 402ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// getBase - Returns the lowest valid address in the region. 412ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// 422ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @result - The lowest valid address. 4336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t getBase() const override = 0; 442ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 452ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// getExtent - Returns the size of the region in bytes. (The region is 462ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// contiguous, so the highest valid address of the region 472ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// is getBase() + getExtent() - 1). 482ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// May block until all bytes in the stream have been read 492ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// 502ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @result - The size of the region. 5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t getExtent() const override = 0; 522ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 532ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// readByte - Tries to read a single byte from the region. 542ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// May block until (address - base) bytes have been read 552ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @param address - The address of the byte, in the same space as getBase(). 562ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL. 572ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @result - 0 if successful; -1 if not. Failure may be due to a 582ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// bounds violation or an implementation-specific error. 5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int readByte(uint64_t address, uint8_t *ptr) const override = 0; 602ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 612ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// readBytes - Tries to read a contiguous range of bytes from the 622ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// region, up to the end of the region. 632ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// May block until (address - base + size) bytes have 642ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// been read. Additionally, StreamableMemoryObjects will 652ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// not do partial reads - if size bytes cannot be read, 662ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// readBytes will fail. 672ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// 682ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @param address - The address of the first byte, in the same space as 692ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// getBase(). 7049a6a8d8f2994249c81b7914b07015714748a55cBenjamin Kramer /// @param size - The number of bytes to copy. 712ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @param buf - A pointer to a buffer to be filled in. Must be non-NULL 722ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// and large enough to hold size bytes. 732ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @result - 0 if successful; -1 if not. Failure may be due to a 742ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// bounds violation or an implementation-specific error. 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int readBytes(uint64_t address, uint64_t size, 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t *buf) const override = 0; 772ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 782ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// getPointer - Ensures that the requested data is in memory, and returns 792ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// A pointer to it. More efficient than using readBytes if the 802ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// data is already in memory. 812ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// May block until (address - base + size) bytes have been read 822ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @param address - address of the byte, in the same space as getBase() 832ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @param size - amount of data that must be available on return 842ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @result - valid pointer to the requested data 85adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const = 0; 862ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 872ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// isValidAddress - Returns true if the address is within the object 882ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// (i.e. between base and base + extent - 1 inclusive) 892ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// May block until (address - base) bytes have been read 902ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @param address - address of the byte, in the same space as getBase() 912ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @result - true if the address may be read with readByte() 92adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff virtual bool isValidAddress(uint64_t address) const = 0; 932ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 942ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// isObjectEnd - Returns true if the address is one past the end of the 952ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// object (i.e. if it is equal to base + extent) 962ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// May block until (address - base) bytes have been read 972ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @param address - address of the byte, in the same space as getBase() 982ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// @result - true if the address is equal to base + extent 99adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff virtual bool isObjectEnd(uint64_t address) const = 0; 1002ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff}; 1012ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 1022ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// StreamingMemoryObject - interface to data which is actually streamed from 1032ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// a DataStreamer. In addition to inherited members, it has the 1042ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// dropLeadingBytes and setKnownObjectSize methods which are not applicable 1052ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff/// to non-streamed objects. 1062ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffclass StreamingMemoryObject : public StreamableMemoryObject { 1072ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffpublic: 1082ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff StreamingMemoryObject(DataStreamer *streamer); 10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t getBase() const override { return 0; } 11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t getExtent() const override; 11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int readByte(uint64_t address, uint8_t *ptr) const override; 11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines int readBytes(uint64_t address, uint64_t size, 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t *buf) const override; 11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const uint8_t *getPointer(uint64_t address, uint64_t size) const override { 1152ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // This could be fixed by ensuring the bytes are fetched and making a copy, 1162ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // requiring that the bitcode size be known, or otherwise ensuring that 1172ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // the memory doesn't go away/get reallocated, but it's 1182ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // not currently necessary. Users that need the pointer don't stream. 119cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines llvm_unreachable("getPointer in streaming memory objects not allowed"); 120dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 1212ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool isValidAddress(uint64_t address) const override; 12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool isObjectEnd(uint64_t address) const override; 1242ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 1252ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// Drop s bytes from the front of the stream, pushing the positions of the 1262ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// remaining bytes down by s. This is used to skip past the bitcode header, 1272ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// since we don't know a priori if it's present, and we can't put bytes 1282ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// back into the stream once we've read them. 1292ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff bool dropLeadingBytes(size_t s); 1302ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 1312ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// If the data object size is known in advance, many of the operations can 1322ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// be made more efficient, so this method should be called before reading 1332ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff /// starts (although it can be called anytime). 1342ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff void setKnownObjectSize(size_t size); 1352ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 1362ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffprivate: 1372ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff const static uint32_t kChunkSize = 4096 * 4; 138adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff mutable std::vector<unsigned char> Bytes; 13936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::unique_ptr<DataStreamer> Streamer; 140adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff mutable size_t BytesRead; // Bytes read from stream 1412ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header) 142adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached 143adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff mutable bool EOFReached; 1442ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 1452ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // Fetch enough bytes such that Pos can be read or EOF is reached 1462ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // (i.e. BytesRead > Pos). Return true if Pos can be read. 1472ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // Unlike most of the functions in BitcodeReader, returns true on success. 1482ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // Most of the requests will be small, but we fetch at kChunkSize bytes 1492ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff // at a time to avoid making too many potentially expensive GetBytes calls 150adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff bool fetchToPos(size_t Pos) const { 1512ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff if (EOFReached) return Pos < ObjectSize; 1522ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff while (Pos >= BytesRead) { 153cd4f803ac1b366084bdf691d5da5563704e36dfeDerek Schuff Bytes.resize(BytesRead + BytesSkipped + kChunkSize); 1542ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped], 1552ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff kChunkSize); 1562ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff BytesRead += bytes; 1572ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff if (bytes < kChunkSize) { 158cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines assert((!ObjectSize || BytesRead >= Pos) && 159cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines "Unexpected short read fetching bitcode"); 1602ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff if (BytesRead <= Pos) { // reached EOF/ran out of bytes 1612ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff ObjectSize = BytesRead; 1622ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff EOFReached = true; 1632ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff return false; 1642ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 1652ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 1662ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 1672ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff return true; 1682ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 1692ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 170f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; 171f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; 1722ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff}; 1732ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 1742ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek SchuffStreamableMemoryObject *getNonStreamedMemoryObject( 1752ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff const unsigned char *Start, const unsigned char *End); 1762ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 1772ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff} 1782ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#endif // STREAMABLEMEMORYOBJECT_H_ 179