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