144ebf8b0331cb3a994a8df16fb63fdcdbc37d927Nick Lewycky//===--- llvm/Support/DataStream.cpp - Lazy streamed data -----------------===// 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// This file implements DataStreamer, which fetches bytes of Data from 112ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// a stream source. It provides support for streaming (lazy reading) of 122ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// bitcode. An example implementation of streaming from a file or stdin 132ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// is included. 142ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// 152ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff//===----------------------------------------------------------------------===// 162ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 172ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#define DEBUG_TYPE "Data-stream" 182ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include "llvm/Support/DataStream.h" 19d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/Statistic.h" 20eb446511ce5f1761962f12f1e8a0c7b342733d1cDerek Schuff#include "llvm/Support/Program.h" 212ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include "llvm/Support/system_error.h" 222ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include <cerrno> 232ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include <cstdio> 24d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include <string> 252ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#if !defined(_MSC_VER) && !defined(__MINGW32__) 262ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include <unistd.h> 272ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#else 282ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include <io.h> 292ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#endif 302ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff#include <fcntl.h> 312ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffusing namespace llvm; 322ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 332ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// Interface goals: 342ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// * StreamableMemoryObject doesn't care about complexities like using 352ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// threads/async callbacks to actually overlap download+compile 362ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// * Don't want to duplicate Data in memory 372ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// * Don't need to know total Data len in advance 382ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// Non-goals: 392ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// StreamableMemoryObject already has random access so this interface only does 402ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// in-order streaming (no arbitrary seeking, else we'd have to buffer all the 412ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// Data here in addition to MemoryObject). This also means that if we want 422ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// to be able to to free Data, BitstreamBytes/BitcodeReader will implement it 432ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 442ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek SchuffSTATISTIC(NumStreamFetches, "Number of calls to Data stream fetch"); 452ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 462ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffnamespace llvm { 472ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek SchuffDataStreamer::~DataStreamer() {} 482ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff} 492ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 502ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffnamespace { 512ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 522ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// Very simple stream backed by a file. Mostly useful for stdin and debugging; 532ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff// actual file access is probably still best done with mmap. 542ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffclass DataFileStreamer : public DataStreamer { 552ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff int Fd; 562ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffpublic: 572ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff DataFileStreamer() : Fd(0) {} 582ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff virtual ~DataFileStreamer() { 592ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff close(Fd); 602ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 61a96a1824747632ce87ef065b4a13fb777d2b14d6Craig Topper virtual size_t GetBytes(unsigned char *buf, size_t len) LLVM_OVERRIDE { 622ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff NumStreamFetches++; 632ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff return read(Fd, buf, len); 642ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 652ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 662ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff error_code OpenFile(const std::string &Filename) { 67eb446511ce5f1761962f12f1e8a0c7b342733d1cDerek Schuff if (Filename == "-") { 682ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff Fd = 0; 69eb446511ce5f1761962f12f1e8a0c7b342733d1cDerek Schuff sys::Program::ChangeStdinToBinary(); 7058604cd944eec4a75046076cb53eb708aaf2ee09David Blaikie return error_code::success(); 71eb446511ce5f1761962f12f1e8a0c7b342733d1cDerek Schuff } 724eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie 734eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie int OpenFlags = O_RDONLY; 744eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie#ifdef O_BINARY 754eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie OpenFlags |= O_BINARY; // Open input file in binary mode on win32. 764eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie#endif 774eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie Fd = ::open(Filename.c_str(), OpenFlags); 784eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie if (Fd == -1) 794eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie return error_code(errno, posix_category()); 8058604cd944eec4a75046076cb53eb708aaf2ee09David Blaikie return error_code::success(); 812ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 822ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff}; 832ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 842ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff} 852ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 862ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuffnamespace llvm { 872ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek SchuffDataStreamer *getDataFileStreamer(const std::string &Filename, 882ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff std::string *StrError) { 892ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff DataFileStreamer *s = new DataFileStreamer(); 904eebfb8b399b1e0a209c971690e108c18c0e1f10David Blaikie if (error_code e = s->OpenFile(Filename)) { 912ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff *StrError = std::string("Could not open ") + Filename + ": " + 922ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff e.message() + "\n"; 932ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff return NULL; 942ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff } 952ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff return s; 962ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff} 972ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff 982ea93875b2f2900b9d244dfd7649c9ed02a34cd7Derek Schuff} 99