Subzero: Switch file reading to be based on a DataStreamer and MemoryObject.

This makes it compatible with the current browser interface,
which pushes bytes to a DataStreamer.

In the browser-integration mode, there will be a push-based
DataStreamer (vs a file-based one).

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4091
R=dschuff@chromium.org, kschimpf@google.com, stichnot@chromium.org

Review URL: https://codereview.chromium.org/982403002
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index d0b099d..2ff57c1 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -2992,43 +2992,27 @@
 
 namespace Ice {
 
-void PNaClTranslator::translate(const std::string &IRFilename) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> ErrOrFile =
-      MemoryBuffer::getFileOrSTDIN(IRFilename);
-  if (std::error_code EC = ErrOrFile.getError()) {
-    errs() << "Error reading '" << IRFilename << "': " << EC.message() << "\n";
-    ErrorStatus.assign(EC.value());
-    return;
-  }
-
-  std::unique_ptr<MemoryBuffer> MemBuf(ErrOrFile.get().release());
-  translateBuffer(IRFilename, MemBuf.get());
-}
-
 void PNaClTranslator::translateBuffer(const std::string &IRFilename,
                                       MemoryBuffer *MemBuf) {
-  if (MemBuf->getBufferSize() % 4 != 0) {
-    errs() << IRFilename
-           << ": Bitcode stream should be a multiple of 4 bytes in length.\n";
-    ErrorStatus.assign(EC_Bitcode);
-    return;
-  }
+  std::unique_ptr<MemoryObject> MemObj(getNonStreamedMemoryObject(
+      reinterpret_cast<const unsigned char *>(MemBuf->getBufferStart()),
+      reinterpret_cast<const unsigned char *>(MemBuf->getBufferEnd())));
+  translate(IRFilename, std::move(MemObj));
+}
 
-  const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart();
-  const unsigned char *HeaderPtr = BufPtr;
-  const unsigned char *EndBufPtr = BufPtr + MemBuf->getBufferSize();
+void PNaClTranslator::translate(const std::string &IRFilename,
+                                std::unique_ptr<MemoryObject> &&MemObj) {
 
   // Read header and verify it is good.
   NaClBitcodeHeader Header;
-  if (Header.Read(HeaderPtr, EndBufPtr) || !Header.IsSupported()) {
+  if (Header.Read(MemObj.get()) || !Header.IsSupported()) {
     errs() << "Invalid PNaCl bitcode header.\n";
     ErrorStatus.assign(EC_Bitcode);
     return;
   }
 
   // Create a bitstream reader to read the bitcode file.
-  NaClBitstreamReader InputStreamFile(BufPtr, EndBufPtr,
-                                      Header.getHeaderSize());
+  NaClBitstreamReader InputStreamFile(MemObj.release(), Header.getHeaderSize());
   NaClBitstreamCursor InputStream(InputStreamFile);
 
   TopLevelParser Parser(*this, InputStream, ErrorStatus);
@@ -3047,6 +3031,12 @@
            << "\n";
     ErrorStatus.assign(EC_Bitcode);
   }
+  if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) {
+    errs() << IRFilename
+           << ": Bitcode stream should be a multiple of 4 bytes in length.\n";
+    ErrorStatus.assign(EC_Bitcode);
+    return;
+  }
 }
 
 } // end of namespace Ice
diff --git a/src/PNaClTranslator.h b/src/PNaClTranslator.h
index 9162d59..e2d423a 100644
--- a/src/PNaClTranslator.h
+++ b/src/PNaClTranslator.h
@@ -21,6 +21,7 @@
 
 namespace llvm {
 class MemoryBuffer;
+class MemoryObject;
 } // end of namespace llvm
 
 namespace Ice {
@@ -35,8 +36,9 @@
 
   // Reads the PNaCl bitcode file and translates to ICE, which is then
   // converted to machine code. Sets ErrorStatus to 1 if any errors
-  // occurred.
-  void translate(const std::string &IRFilename);
+  // occurred. Takes ownership of the MemoryObject.
+  void translate(const std::string &IRFilename,
+                 std::unique_ptr<llvm::MemoryObject> &&MemoryObject);
 
   // Reads MemBuf, assuming it is the PNaCl bitcode contents of IRFilename.
   void translateBuffer(const std::string &IRFilename,
diff --git a/src/main.cpp b/src/main.cpp
index 8ced212..22ab0a1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -26,6 +26,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_os_ostream.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/StreamingMemoryObject.h"
 
 #include "IceCfg.h"
 #include "IceClFlags.h"
@@ -379,7 +380,17 @@
   if (BuildOnRead) {
     std::unique_ptr<Ice::PNaClTranslator> PTranslator(
         new Ice::PNaClTranslator(&Ctx));
-    PTranslator->translate(IRFilename);
+    std::string StrError;
+    std::unique_ptr<DataStreamer> FileStreamer(
+        getDataFileStreamer(IRFilename, &StrError));
+    if (!StrError.empty() || !FileStreamer) {
+      SMDiagnostic Err(IRFilename, SourceMgr::DK_Error, StrError);
+      Err.print(argv[0], errs());
+      return GetReturnValue(Ice::EC_Bitcode);
+    }
+    std::unique_ptr<StreamingMemoryObject> MemObj(
+        new StreamingMemoryObjectImpl(FileStreamer.release()));
+    PTranslator->translate(IRFilename, std::move(MemObj));
     Translator.reset(PTranslator.release());
   } else if (ALLOW_LLVM_IR) {
     // Parse the input LLVM IR file into a module.