1234285Sdim//===--- llvm/Support/DataStream.cpp - Lazy streamed data -----------------===// 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// This file implements DataStreamer, which fetches bytes of Data from 11234285Sdim// a stream source. It provides support for streaming (lazy reading) of 12234285Sdim// bitcode. An example implementation of streaming from a file or stdin 13234285Sdim// is included. 14234285Sdim// 15234285Sdim//===----------------------------------------------------------------------===// 16234285Sdim 17249423Sdim#include "llvm/Support/DataStream.h" 18234285Sdim#include "llvm/ADT/Statistic.h" 19288943Sdim#include "llvm/ADT/STLExtras.h" 20261991Sdim#include "llvm/Support/FileSystem.h" 21234285Sdim#include "llvm/Support/Program.h" 22249423Sdim#include <string> 23276479Sdim#include <system_error> 24234285Sdim#if !defined(_MSC_VER) && !defined(__MINGW32__) 25234285Sdim#include <unistd.h> 26234285Sdim#else 27234285Sdim#include <io.h> 28234285Sdim#endif 29234285Sdimusing namespace llvm; 30234285Sdim 31276479Sdim#define DEBUG_TYPE "Data-stream" 32276479Sdim 33234285Sdim// Interface goals: 34280031Sdim// * StreamingMemoryObject doesn't care about complexities like using 35234285Sdim// threads/async callbacks to actually overlap download+compile 36234285Sdim// * Don't want to duplicate Data in memory 37234285Sdim// * Don't need to know total Data len in advance 38234285Sdim// Non-goals: 39280031Sdim// StreamingMemoryObject already has random access so this interface only does 40234285Sdim// in-order streaming (no arbitrary seeking, else we'd have to buffer all the 41234285Sdim// Data here in addition to MemoryObject). This also means that if we want 42234285Sdim// to be able to to free Data, BitstreamBytes/BitcodeReader will implement it 43234285Sdim 44234285SdimSTATISTIC(NumStreamFetches, "Number of calls to Data stream fetch"); 45234285Sdim 46234285Sdimnamespace llvm { 47234285SdimDataStreamer::~DataStreamer() {} 48234285Sdim} 49234285Sdim 50234285Sdimnamespace { 51234285Sdim 52234285Sdim// Very simple stream backed by a file. Mostly useful for stdin and debugging; 53234285Sdim// actual file access is probably still best done with mmap. 54234285Sdimclass DataFileStreamer : public DataStreamer { 55234285Sdim int Fd; 56234285Sdimpublic: 57234285Sdim DataFileStreamer() : Fd(0) {} 58288943Sdim ~DataFileStreamer() override { close(Fd); } 59276479Sdim size_t GetBytes(unsigned char *buf, size_t len) override { 60234285Sdim NumStreamFetches++; 61234285Sdim return read(Fd, buf, len); 62234285Sdim } 63234285Sdim 64276479Sdim std::error_code OpenFile(const std::string &Filename) { 65234285Sdim if (Filename == "-") { 66234285Sdim Fd = 0; 67261991Sdim sys::ChangeStdinToBinary(); 68276479Sdim return std::error_code(); 69234285Sdim } 70261991Sdim 71261991Sdim return sys::fs::openFileForRead(Filename, Fd); 72234285Sdim } 73234285Sdim}; 74234285Sdim 75234285Sdim} 76234285Sdim 77288943Sdimstd::unique_ptr<DataStreamer> 78288943Sdimllvm::getDataFileStreamer(const std::string &Filename, std::string *StrError) { 79288943Sdim std::unique_ptr<DataFileStreamer> s = make_unique<DataFileStreamer>(); 80276479Sdim if (std::error_code e = s->OpenFile(Filename)) { 81234285Sdim *StrError = std::string("Could not open ") + Filename + ": " + 82234285Sdim e.message() + "\n"; 83276479Sdim return nullptr; 84234285Sdim } 85288943Sdim return std::move(s); 86234285Sdim} 87