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