LLVM API Documentation
00001 //===- StreamableMemoryObject.cpp - Streamable data interface -------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "llvm/Support/StreamableMemoryObject.h" 00011 #include "llvm/Support/Compiler.h" 00012 #include <cassert> 00013 #include <cstddef> 00014 #include <cstring> 00015 00016 00017 using namespace llvm; 00018 00019 namespace { 00020 00021 class RawMemoryObject : public StreamableMemoryObject { 00022 public: 00023 RawMemoryObject(const unsigned char *Start, const unsigned char *End) : 00024 FirstChar(Start), LastChar(End) { 00025 assert(LastChar >= FirstChar && "Invalid start/end range"); 00026 } 00027 00028 uint64_t getBase() const override { return 0; } 00029 uint64_t getExtent() const override { 00030 return LastChar - FirstChar; 00031 } 00032 int readByte(uint64_t address, uint8_t* ptr) const override; 00033 int readBytes(uint64_t address, uint64_t size, 00034 uint8_t *buf) const override; 00035 const uint8_t *getPointer(uint64_t address, uint64_t size) const override; 00036 bool isValidAddress(uint64_t address) const override { 00037 return validAddress(address); 00038 } 00039 bool isObjectEnd(uint64_t address) const override { 00040 return objectEnd(address); 00041 } 00042 00043 private: 00044 const uint8_t* const FirstChar; 00045 const uint8_t* const LastChar; 00046 00047 // These are implemented as inline functions here to avoid multiple virtual 00048 // calls per public function 00049 bool validAddress(uint64_t address) const { 00050 return static_cast<std::ptrdiff_t>(address) < LastChar - FirstChar; 00051 } 00052 bool objectEnd(uint64_t address) const { 00053 return static_cast<std::ptrdiff_t>(address) == LastChar - FirstChar; 00054 } 00055 00056 RawMemoryObject(const RawMemoryObject&) LLVM_DELETED_FUNCTION; 00057 void operator=(const RawMemoryObject&) LLVM_DELETED_FUNCTION; 00058 }; 00059 00060 int RawMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { 00061 if (!validAddress(address)) return -1; 00062 *ptr = *((uint8_t *)(uintptr_t)(address + FirstChar)); 00063 return 0; 00064 } 00065 00066 int RawMemoryObject::readBytes(uint64_t address, 00067 uint64_t size, 00068 uint8_t *buf) const { 00069 if (!validAddress(address) || !validAddress(address + size - 1)) return -1; 00070 memcpy(buf, (uint8_t *)(uintptr_t)(address + FirstChar), size); 00071 return size; 00072 } 00073 00074 const uint8_t *RawMemoryObject::getPointer(uint64_t address, 00075 uint64_t size) const { 00076 return FirstChar + address; 00077 } 00078 } // anonymous namespace 00079 00080 namespace llvm { 00081 // If the bitcode has a header, then its size is known, and we don't have to 00082 // block until we actually want to read it. 00083 bool StreamingMemoryObject::isValidAddress(uint64_t address) const { 00084 if (ObjectSize && address < ObjectSize) return true; 00085 return fetchToPos(address); 00086 } 00087 00088 bool StreamingMemoryObject::isObjectEnd(uint64_t address) const { 00089 if (ObjectSize) return address == ObjectSize; 00090 fetchToPos(address); 00091 return address == ObjectSize && address != 0; 00092 } 00093 00094 uint64_t StreamingMemoryObject::getExtent() const { 00095 if (ObjectSize) return ObjectSize; 00096 size_t pos = BytesRead + kChunkSize; 00097 // keep fetching until we run out of bytes 00098 while (fetchToPos(pos)) pos += kChunkSize; 00099 return ObjectSize; 00100 } 00101 00102 int StreamingMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { 00103 if (!fetchToPos(address)) return -1; 00104 *ptr = Bytes[address + BytesSkipped]; 00105 return 0; 00106 } 00107 00108 int StreamingMemoryObject::readBytes(uint64_t address, 00109 uint64_t size, 00110 uint8_t *buf) const { 00111 if (!fetchToPos(address + size - 1)) return -1; 00112 memcpy(buf, &Bytes[address + BytesSkipped], size); 00113 return 0; 00114 } 00115 00116 bool StreamingMemoryObject::dropLeadingBytes(size_t s) { 00117 if (BytesRead < s) return true; 00118 BytesSkipped = s; 00119 BytesRead -= s; 00120 return false; 00121 } 00122 00123 void StreamingMemoryObject::setKnownObjectSize(size_t size) { 00124 ObjectSize = size; 00125 Bytes.reserve(size); 00126 } 00127 00128 StreamableMemoryObject *getNonStreamedMemoryObject( 00129 const unsigned char *Start, const unsigned char *End) { 00130 return new RawMemoryObject(Start, End); 00131 } 00132 00133 StreamableMemoryObject::~StreamableMemoryObject() { } 00134 00135 StreamingMemoryObject::StreamingMemoryObject(DataStreamer *streamer) : 00136 Bytes(kChunkSize), Streamer(streamer), BytesRead(0), BytesSkipped(0), 00137 ObjectSize(0), EOFReached(false) { 00138 BytesRead = streamer->GetBytes(&Bytes[0], kChunkSize); 00139 } 00140 }