Switch the bitcode reader interface to take a MemoryBuffer instead of knowing
authorChris Lattner <sabre@nondot.org>
Sun, 29 Apr 2007 07:54:31 +0000 (07:54 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 29 Apr 2007 07:54:31 +0000 (07:54 +0000)
anything about disk I/O itself.  This greatly simplifies its interface -
eliminating the need for the ReaderWrappers.cpp file.

This adds a new option to llvm-dis (-bitcode) which instructs it to read
the input file as bitcode.  Until/unless the bytecode reader is taught to
read from MemoryBuffer, there is no way to handle stdin reading without it.

I don't plan to switch the bytecode reader over, I'd rather delete it :),
so the option will stay around temporarily.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36554 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Bitcode/ReaderWriter.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Reader/BitcodeReader.h
lib/Bitcode/Reader/ReaderWrappers.cpp [deleted file]
tools/llvm-dis/llvm-dis.cpp

index 0522f1bb28eff42b1b08870b9dce7a98f3e933e9..a37cc7bf4c4fefb5020cacd4cf407895639ba758 100644 (file)
 namespace llvm {
   class Module;
   class ModuleProvider;
+  class MemoryBuffer;
   
-  ModuleProvider *getBitcodeModuleProvider(const std::string &Filename,
+  /// getBitcodeModuleProvider - Read the header of the specified bitcode buffer
+  /// and prepare for lazy deserialization of function bodies.  If successful,
+  /// this takes ownership of 'buffer' and returns a non-null pointer.  On
+  /// error, this returns null, *does not* take ownership of Buffer, and fills
+  /// in *ErrMsg with an error description if ErrMsg is non-null.
+  ModuleProvider *getBitcodeModuleProvider(MemoryBuffer *Buffer,
                                            std::string *ErrMsg = 0);
 
-  
   /// ParseBitcodeFile - Read the specified bitcode file, returning the module.
-  /// If an error occurs, return null and fill in *ErrMsg if non-null.
-  Module *ParseBitcodeFile(const std::string &Filename,
-                           std::string *ErrMsg = 0);
+  /// If an error occurs, this returns null and fills in *ErrMsg if it is
+  /// non-null.  This method *never* takes ownership of Buffer.
+  Module *ParseBitcodeFile(MemoryBuffer *Buffer, std::string *ErrMsg = 0);
   
   /// WriteBitcodeToFile - Write the specified module to the specified output
   /// stream.
index 2a6de412cdba1af639481e2c34259e446a70525b..6157a5db5d9c112b244b46bf93bd9d83144d977c 100644 (file)
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/Bitcode/ReaderWriter.h"
 #include "BitcodeReader.h"
 #include "llvm/Bitcode/BitstreamReader.h"
 #include "llvm/Constants.h"
 #include "llvm/Module.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
 using namespace llvm;
 
+BitcodeReader::~BitcodeReader() {
+  delete Buffer;
+}
+
+
 /// ConvertToString - Convert a string from a record into an std::string, return
 /// true on failure.
 template<typename StrTy>
@@ -852,14 +859,14 @@ bool BitcodeReader::ParseModule(BitstreamReader &Stream,
 }
 
 
-bool BitcodeReader::ParseBitcode(unsigned char *Buf, unsigned Length,
-                                 const std::string &ModuleID) {
+bool BitcodeReader::ParseBitcode() {
   TheModule = 0;
   
-  if (Length & 3)
+  if (Buffer->getBufferSize() & 3)
     return Error("Bitcode stream should be a multiple of 4 bytes in length");
   
-  BitstreamReader Stream(Buf, Buf+Length);
+  unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
+  BitstreamReader Stream(BufPtr, BufPtr+Buffer->getBufferSize());
   
   // Sniff for the signature.
   if (Stream.Read(8) != 'B' ||
@@ -882,7 +889,7 @@ bool BitcodeReader::ParseBitcode(unsigned char *Buf, unsigned Length,
     
     // We only know the MODULE subblock ID.
     if (BlockID == bitc::MODULE_BLOCK_ID) {
-      if (ParseModule(Stream, ModuleID))
+      if (ParseModule(Stream, Buffer->getBufferIdentifier()))
         return true;
     } else if (Stream.SkipBlock()) {
       return Error("Malformed block record");
@@ -891,3 +898,41 @@ bool BitcodeReader::ParseBitcode(unsigned char *Buf, unsigned Length,
   
   return false;
 }
+
+//===----------------------------------------------------------------------===//
+// External interface
+//===----------------------------------------------------------------------===//
+
+/// getBitcodeModuleProvider - lazy function-at-a-time loading from a file.
+///
+ModuleProvider *llvm::getBitcodeModuleProvider(MemoryBuffer *Buffer,
+                                               std::string *ErrMsg) {
+  BitcodeReader *R = new BitcodeReader(Buffer);
+  if (R->ParseBitcode()) {
+    if (ErrMsg)
+      *ErrMsg = R->getErrorString();
+    
+    // Don't let the BitcodeReader dtor delete 'Buffer'.
+    R->releaseMemoryBuffer();
+    delete R;
+    return 0;
+  }
+  return R;
+}
+
+/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
+/// If an error occurs, return null and fill in *ErrMsg if non-null.
+Module *llvm::ParseBitcodeFile(MemoryBuffer *Buffer, std::string *ErrMsg){
+  BitcodeReader *R;
+  R = static_cast<BitcodeReader*>(getBitcodeModuleProvider(Buffer, ErrMsg));
+  if (!R) return 0;
+  
+  // Read the whole module, get a pointer to it, tell ModuleProvider not to
+  // delete it when its dtor is run.
+  Module *M = R->releaseModule(ErrMsg);
+  
+  // Don't let the BitcodeReader dtor delete 'Buffer'.
+  R->releaseMemoryBuffer();
+  delete R;
+  return M;
+}
index 8e211346026b73d7e57ece2267cb21da2dcebca3..0935c06f93ccde4d0d636d619b18f063978c109e 100644 (file)
@@ -22,6 +22,7 @@
 
 namespace llvm {
   class BitstreamReader;
+  class MemoryBuffer;
   
 class BitcodeReaderValueList : public User {
   std::vector<Use> Uses;
@@ -57,6 +58,7 @@ public:
   
 
 class BitcodeReader : public ModuleProvider {
+  MemoryBuffer *Buffer;
   const char *ErrorString;
   
   std::vector<PATypeHolder> TypeList;
@@ -64,10 +66,16 @@ class BitcodeReader : public ModuleProvider {
   std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
   std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
 public:
-  BitcodeReader() : ErrorString(0) {}
-  virtual ~BitcodeReader() {}
+  BitcodeReader(MemoryBuffer *buffer) : Buffer(buffer), ErrorString(0) {}
+  ~BitcodeReader();
   
-  virtual void FreeState() {}
+  
+  /// releaseMemoryBuffer - This causes the reader to completely forget about
+  /// the memory buffer it contains, which prevents the buffer from being
+  /// destroyed when it is deleted.
+  void releaseMemoryBuffer() {
+    Buffer = 0;
+  }
   
   virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0) {
     // FIXME: TODO
@@ -89,8 +97,7 @@ public:
   
   /// @brief Main interface to parsing a bitcode buffer.
   /// @returns true if an error occurred.
-  bool ParseBitcode(unsigned char *Buf, unsigned Length,
-                    const std::string &ModuleID);
+  bool ParseBitcode();
 private:
   const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
   
diff --git a/lib/Bitcode/Reader/ReaderWrappers.cpp b/lib/Bitcode/Reader/ReaderWrappers.cpp
deleted file mode 100644 (file)
index 8bf81a2..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-//===- ReaderWrappers.cpp - Parse bitcode from file or buffer -------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file was developed by Chris Lattner and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements loading and parsing a bitcode file and parsing a
-// module from a memory buffer.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "BitcodeReader.h"
-#include "llvm/System/MappedFile.h"
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// BitcodeFileReader - Read from an mmap'able file descriptor.
-
-namespace {
-  /// BitcodeFileReader - parses bitcode from a file.
-  ///
-  class BitcodeFileReader : public BitcodeReader {
-  private:
-    std::string Filename;
-    sys::MappedFile File;
-    
-    BitcodeFileReader(const BitcodeFileReader&); // DO NOT IMPLEMENT
-    void operator=(const BitcodeFileReader&); // DO NOT IMPLEMENT
-  public:
-    BitcodeFileReader(const std::string &FN) : Filename(FN) {}
-    bool Read(std::string *ErrMsg);
-    
-    void FreeState() {
-      BitcodeReader::FreeState();
-      File.close();
-    }
-  };
-}
-
-bool BitcodeFileReader::Read(std::string *ErrMsg) {
-  if (File.open(sys::Path(Filename), sys::MappedFile::READ_ACCESS, ErrMsg))
-    return true;
-  if (!File.map(ErrMsg)) {
-    File.close();
-    return true;
-  }
-  unsigned char *Buffer = reinterpret_cast<unsigned char*>(File.base());
-  if (!ParseBitcode(Buffer, File.size(), Filename))
-    return false;
-  assert(getErrorString() && "Didn't set an error string?");
-  if (ErrMsg) *ErrMsg = getErrorString();
-  return true;
-}
-
-
-
-//===----------------------------------------------------------------------===//
-// External interface
-//===----------------------------------------------------------------------===//
-
-/// getBitcodeModuleProvider - lazy function-at-a-time loading from a file.
-///
-ModuleProvider *llvm::getBitcodeModuleProvider(const std::string &Filename,
-                                               std::string *ErrMsg) {
-  if (Filename != std::string("-")) {
-    BitcodeFileReader *R = new BitcodeFileReader(Filename);
-    if (R->Read(ErrMsg)) {
-      delete R;
-      return 0;
-    }
-    return R;
-  }
-  
-  assert(0 && "FIXME: stdin reading unimp!");
-#if 0
-  // Read from stdin
-  BytecodeStdinReader *R = new BytecodeStdinReader();
-  if (R->Read(ErrMsg)) {
-    delete R;
-    return 0;
-  }
-  return R;
-#endif
-}
-
-/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
-/// If an error occurs, return null and fill in *ErrMsg if non-null.
-Module *llvm::ParseBitcodeFile(const std::string &Filename,std::string *ErrMsg){
-  ModuleProvider *MP = getBitcodeModuleProvider(Filename, ErrMsg);
-  if (!MP) return 0;
-  Module *M = MP->releaseModule(ErrMsg);
-  delete MP;
-  return M;
-}
index bb91ad6fce6ed2b3efb7f4a5c5576089b2265281..6065e9ba5e768ca5b65380c296a02de5f86c04cd 100644 (file)
@@ -24,6 +24,7 @@
 #include "llvm/Support/Compressor.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Streams.h"
 #include "llvm/System/Signals.h"
 #include <iostream>
@@ -44,6 +45,9 @@ Force("f", cl::desc("Overwrite output files"));
 static cl::opt<bool>
 DontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
 
+static cl::opt<bool>
+Bitcode("bitcode", cl::desc("Read a bitcode file"));
+
 int main(int argc, char **argv) {
   llvm_shutdown_obj X;  // Call llvm_shutdown() on exit.
   try {
@@ -55,12 +59,26 @@ int main(int argc, char **argv) {
 
     std::auto_ptr<Module> M;
    
-    if (InputFilename != "-") 
-      M.reset(ParseBitcodeFile(InputFilename, &ErrorMessage));
-    
-    if (M.get() == 0)
-      M.reset(ParseBytecodeFile(InputFilename,Compressor::decompressToNewBuffer,
+    if (Bitcode) {
+      MemoryBuffer *Buffer;
+      if (InputFilename == "-") {
+        Buffer = MemoryBuffer::getSTDIN();
+      } else {
+        Buffer = MemoryBuffer::getFile(&InputFilename[0], InputFilename.size());
+      }
+
+      if (Buffer == 0)
+        ErrorMessage = "Error reading file '" + InputFilename + "'";
+      else
+        M.reset(ParseBitcodeFile(Buffer, &ErrorMessage));
+      
+      delete Buffer;
+    } else {
+      M.reset(ParseBytecodeFile(InputFilename,
+                                Compressor::decompressToNewBuffer,
                                 &ErrorMessage));
+    }
+
     if (M.get() == 0) {
       cerr << argv[0] << ": ";
       if (ErrorMessage.size())
@@ -69,7 +87,7 @@ int main(int argc, char **argv) {
         cerr << "bytecode didn't read correctly.\n";
       return 1;
     }
-
+    
     if (DontPrint) {
       // Just use stdout.  We won't actually print anything on it.
     } else if (OutputFilename != "") {   // Specified an output filename?