[llvm] r239871 - Handle forward referenced function when streaming bitcode.

Rafael Espindola rafael.espindola at gmail.com
Tue Jun 16 18:15:47 PDT 2015


Author: rafael
Date: Tue Jun 16 20:15:47 2015
New Revision: 239871

URL: http://llvm.org/viewvc/llvm-project?rev=239871&view=rev
Log:
Handle forward referenced function when streaming bitcode.

Without this the included unit test would assert in

  assert(BasicBlockFwdRefs.empty() && "Unresolved blockaddress fwd references");

Modified:
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/unittests/Bitcode/BitReaderTest.cpp

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=239871&r1=239870&r2=239871&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Tue Jun 16 20:15:47 2015
@@ -4597,23 +4597,11 @@ const std::error_category &llvm::Bitcode
 // External interface
 //===----------------------------------------------------------------------===//
 
-/// \brief Get a lazy one-at-time loading module from bitcode.
-///
-/// This isn't always used in a lazy context.  In particular, it's also used by
-/// \a parseBitcodeFile().  If this is truly lazy, then we need to eagerly pull
-/// in forward-referenced functions from block address references.
-///
-/// \param[in] MaterializeAll Set to \c true if we should materialize
-/// everything.
 static ErrorOr<std::unique_ptr<Module>>
-getLazyBitcodeModuleImpl(std::unique_ptr<MemoryBuffer> &&Buffer,
-                         LLVMContext &Context, bool MaterializeAll,
-                         DiagnosticHandlerFunction DiagnosticHandler,
-                         bool ShouldLazyLoadMetadata = false) {
-  std::unique_ptr<Module> M =
-      make_unique<Module>(Buffer->getBufferIdentifier(), Context);
-  BitcodeReader *R =
-      new BitcodeReader(Buffer.get(), Context, DiagnosticHandler);
+getBitcodeModuleImpl(std::unique_ptr<DataStreamer> Streamer, StringRef Name,
+                     BitcodeReader *R, LLVMContext &Context,
+                     bool MaterializeAll, bool ShouldLazyLoadMetadata) {
+  std::unique_ptr<Module> M = make_unique<Module>(Name, Context);
   M->setMaterializer(R);
 
   auto cleanupOnError = [&](std::error_code EC) {
@@ -4622,22 +4610,46 @@ getLazyBitcodeModuleImpl(std::unique_ptr
   };
 
   // Delay parsing Metadata if ShouldLazyLoadMetadata is true.
-  if (std::error_code EC =
-          R->parseBitcodeInto(nullptr, M.get(), ShouldLazyLoadMetadata))
+  if (std::error_code EC = R->parseBitcodeInto(std::move(Streamer), M.get(),
+                                               ShouldLazyLoadMetadata))
     return cleanupOnError(EC);
 
   if (MaterializeAll) {
     // Read in the entire module, and destroy the BitcodeReader.
     if (std::error_code EC = M->materializeAllPermanently())
-      return EC;
+      return cleanupOnError(EC);
   } else {
     // Resolve forward references from blockaddresses.
     if (std::error_code EC = R->materializeForwardReferencedFunctions())
       return cleanupOnError(EC);
   }
+  return std::move(M);
+}
+
+/// \brief Get a lazy one-at-time loading module from bitcode.
+///
+/// This isn't always used in a lazy context.  In particular, it's also used by
+/// \a parseBitcodeFile().  If this is truly lazy, then we need to eagerly pull
+/// in forward-referenced functions from block address references.
+///
+/// \param[in] MaterializeAll Set to \c true if we should materialize
+/// everything.
+static ErrorOr<std::unique_ptr<Module>>
+getLazyBitcodeModuleImpl(std::unique_ptr<MemoryBuffer> &&Buffer,
+                         LLVMContext &Context, bool MaterializeAll,
+                         DiagnosticHandlerFunction DiagnosticHandler,
+                         bool ShouldLazyLoadMetadata = false) {
+  BitcodeReader *R =
+      new BitcodeReader(Buffer.get(), Context, DiagnosticHandler);
+
+  ErrorOr<std::unique_ptr<Module>> Ret =
+      getBitcodeModuleImpl(nullptr, Buffer->getBufferIdentifier(), R, Context,
+                           MaterializeAll, ShouldLazyLoadMetadata);
+  if (!Ret)
+    return Ret;
 
   Buffer.release(); // The BitcodeReader owns it now.
-  return std::move(M);
+  return Ret;
 }
 
 ErrorOr<std::unique_ptr<Module>> llvm::getLazyBitcodeModule(
@@ -4652,10 +4664,9 @@ ErrorOr<std::unique_ptr<Module>> llvm::g
     LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler) {
   std::unique_ptr<Module> M = make_unique<Module>(Name, Context);
   BitcodeReader *R = new BitcodeReader(Context, DiagnosticHandler);
-  M->setMaterializer(R);
-  if (std::error_code EC = R->parseBitcodeInto(std::move(Streamer), M.get()))
-    return EC;
-  return std::move(M);
+
+  return getBitcodeModuleImpl(std::move(Streamer), Name, R, Context, false,
+                              false);
 }
 
 ErrorOr<std::unique_ptr<Module>>

Modified: llvm/trunk/unittests/Bitcode/BitReaderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Bitcode/BitReaderTest.cpp?rev=239871&r1=239870&r2=239871&view=diff
==============================================================================
--- llvm/trunk/unittests/Bitcode/BitReaderTest.cpp (original)
+++ llvm/trunk/unittests/Bitcode/BitReaderTest.cpp Tue Jun 16 20:15:47 2015
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/Bitcode/BitstreamWriter.h"
 #include "llvm/Bitcode/ReaderWriter.h"
@@ -16,6 +17,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Verifier.h"
+#include "llvm/Support/DataStream.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
@@ -58,6 +60,49 @@ static std::unique_ptr<Module> getLazyMo
   return std::move(ModuleOrErr.get());
 }
 
+class BufferDataStreamer : public DataStreamer {
+  std::unique_ptr<MemoryBuffer> Buffer;
+  unsigned Pos = 0;
+  size_t GetBytes(unsigned char *Out, size_t Len) override {
+    StringRef Buf = Buffer->getBuffer();
+    size_t Left = Buf.size() - Pos;
+    Len = std::min(Left, Len);
+    memcpy(Out, Buffer->getBuffer().substr(Pos).data(), Len);
+    Pos += Len;
+    return Len;
+  }
+
+public:
+  BufferDataStreamer(std::unique_ptr<MemoryBuffer> Buffer)
+      : Buffer(std::move(Buffer)) {}
+};
+
+static std::unique_ptr<Module>
+getStreamedModuleFromAssembly(LLVMContext &Context, SmallString<1024> &Mem,
+                              const char *Assembly) {
+  writeModuleToBuffer(parseAssembly(Assembly), Mem);
+  std::unique_ptr<MemoryBuffer> Buffer =
+      MemoryBuffer::getMemBuffer(Mem.str(), "test", false);
+  auto Streamer = make_unique<BufferDataStreamer>(std::move(Buffer));
+  ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
+      getStreamedBitcodeModule("test", std::move(Streamer), Context);
+  return std::move(ModuleOrErr.get());
+}
+
+TEST(BitReaderTest, MateralizeForwardRefWithStream) {
+  SmallString<1024> Mem;
+
+  LLVMContext Context;
+  std::unique_ptr<Module> M = getStreamedModuleFromAssembly(
+      Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"
+                    "define void @func() {\n"
+                    "  unreachable\n"
+                    "bb:\n"
+                    "  unreachable\n"
+                    "}\n");
+  EXPECT_FALSE(M->getFunction("func")->empty());
+}
+
 TEST(BitReaderTest, DematerializeFunctionPreservesLinkageType) {
   SmallString<1024> Mem;
 





More information about the llvm-commits mailing list