Materialize functions whose basic blocks are used by global variables. Fixes
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 2 Jan 2012 07:49:53 +0000 (07:49 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 2 Jan 2012 07:49:53 +0000 (07:49 +0000)
PR11677.

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

lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Reader/BitcodeReader.h
unittests/CMakeLists.txt
unittests/VMCore/pr11677.cpp [new file with mode: 0644]

index b86d6e088333954942748be93396ac3aec398abf..9d10498943e0302539dbd24b1b8841751c2198ba 100644 (file)
 #include "llvm/OperandTraits.h"
 using namespace llvm;
 
+void BitcodeReader::materializeForwardReferencedFunctions() {
+  while (!BlockAddrFwdRefs.empty()) {
+    Function *F = BlockAddrFwdRefs.begin()->first;
+    F->Materialize();
+  }
+}
+
 void BitcodeReader::FreeState() {
   if (BufferOwned)
     delete Buffer;
@@ -2779,6 +2786,9 @@ Module *llvm::getLazyBitcodeModule(MemoryBuffer *Buffer,
   }
   // Have the BitcodeReader dtor delete 'Buffer'.
   R->setBufferOwned(true);
+
+  R->materializeForwardReferencedFunctions();
+
   return M;
 }
 
index 978b15b0f0cdaa976fc367c3d2aab44ee56ef8c9..952d645a4c3eea9c19302845fbd4dc084668bc43 100644 (file)
@@ -184,7 +184,9 @@ public:
   ~BitcodeReader() {
     FreeState();
   }
-  
+
+  void materializeForwardReferencedFunctions();
+
   void FreeState();
   
   /// setBufferOwned - If this is true, the reader will destroy the MemoryBuffer
index 2eff1642c41a7b0390c804f7815313ddfa56cf73..3cd7f2f051dacccfff5faef0b854a19cffb8b7c8 100644 (file)
@@ -112,6 +112,7 @@ set(VMCoreSources
   VMCore/PassManagerTest.cpp
   VMCore/ValueMapTest.cpp
   VMCore/VerifierTest.cpp
+  VMCore/pr11677.cpp
   )
 
 # MSVC9 and 8 cannot compile ValueMapTest.cpp due to their bug.
diff --git a/unittests/VMCore/pr11677.cpp b/unittests/VMCore/pr11677.cpp
new file mode 100644 (file)
index 0000000..362eec7
--- /dev/null
@@ -0,0 +1,64 @@
+//===- llvm/unittest/VMCore/pr11677.cpp - Test for blockaddr --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Constants.h"
+#include "llvm/Instructions.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace {
+
+static Module *makeLLVMModule() {
+  Module* Mod = new Module("test-mem", getGlobalContext());
+
+  FunctionType* FuncTy =
+    FunctionType::get(Type::getVoidTy(Mod->getContext()), false);
+  Function* Func = Function::Create(FuncTy,GlobalValue::ExternalLinkage,
+                                    "func", Mod);
+
+  BasicBlock* Entry = BasicBlock::Create(Mod->getContext(), "entry", Func);
+  new UnreachableInst(Mod->getContext(), Entry);
+
+  BasicBlock* BB = BasicBlock::Create(Mod->getContext(), "bb", Func);
+  new UnreachableInst(Mod->getContext(), BB);
+
+  PointerType* Int8Ptr = Type::getInt8PtrTy(Mod->getContext());
+  new GlobalVariable(*Mod, Int8Ptr, /*isConstant=*/true,
+                     GlobalValue::ExternalLinkage,
+                     BlockAddress::get(BB), "table");
+
+  return Mod;
+}
+
+static void writeModuleToBuffer(std::vector<unsigned char> &Buffer) {
+  Module *Mod = makeLLVMModule();
+  BitstreamWriter Stream(Buffer);
+  WriteBitcodeToStream(Mod, Stream);
+}
+
+TEST(PR11677, BlockAddr) {
+  std::vector<unsigned char> Mem;
+  writeModuleToBuffer(Mem);
+  StringRef Data((const char*)&Mem[0], Mem.size());
+  MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Data, "test", false);
+  std::string errMsg;
+  Module *m = getLazyBitcodeModule(Buffer, getGlobalContext(), &errMsg);
+  PassManager passes;
+  passes.add(createVerifierPass());
+  passes.run(*m);
+}
+}
+}