llvm.org GIT mirror llvm / 1b27914 unittests / Bitcode / BitReaderTest.cpp
1b27914

Tree @1b27914 (Download .tar.gz)

BitReaderTest.cpp @1b27914

972cc0d
47f79bb
 
 
 
 
 
 
 
fdc8f78
1b27914
47f79bb
 
0b8c9a8
 
 
 
56e1394
2e9b60a
47f79bb
2e9b60a
47f79bb
 
2e9b60a
47f79bb
2e9b60a
47f79bb
2e9b60a
 
9b29ff9
 
47f79bb
2e9b60a
 
 
47f79bb
2e9b60a
9b29ff9
2e9b60a
47f79bb
2e9b60a
47f79bb
 
2e9b60a
 
fdc8f78
023d97d
47f79bb
 
2e9b60a
 
 
 
1a7f705
 
6d66a1c
 
2e9b60a
47f79bb
972cc0d
fd42335
 
 
 
 
 
 
 
 
 
 
c498284
fd42335
 
 
 
 
 
 
 
 
 
 
 
2e9b60a
 
 
 
 
 
 
 
 
 
 
 
cf8b959
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c498284
cf8b959
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c498284
cf8b959
 
 
 
 
 
 
 
47f79bb
2e9b60a
 
//===- llvm/unittest/Bitcode/BitReaderTest.cpp - Tests for BitReader ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/SmallString.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

std::unique_ptr<Module> parseAssembly(const char *Assembly) {
  SMDiagnostic Error;
  std::unique_ptr<Module> M =
      parseAssemblyString(Assembly, Error, getGlobalContext());

  std::string ErrMsg;
  raw_string_ostream OS(ErrMsg);
  Error.print("", OS);

  // A failure here means that the test itself is buggy.
  if (!M)
    report_fatal_error(OS.str().c_str());

  return M;
}

static void writeModuleToBuffer(std::unique_ptr<Module> Mod,
                                SmallVectorImpl<char> &Buffer) {
  raw_svector_ostream OS(Buffer);
  WriteBitcodeToFile(Mod.get(), OS);
}

static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context,
                                                         SmallString<1024> &Mem,
                                                         const char *Assembly) {
  writeModuleToBuffer(parseAssembly(Assembly), Mem);
  std::unique_ptr<MemoryBuffer> Buffer =
      MemoryBuffer::getMemBuffer(Mem.str(), "test", false);
  ErrorOr<Module *> ModuleOrErr =
      getLazyBitcodeModule(std::move(Buffer), Context);
  return std::unique_ptr<Module>(ModuleOrErr.get());
}

TEST(BitReaderTest, DematerializeFunctionPreservesLinkageType) {
  SmallString<1024> Mem;

  LLVMContext Context;
  std::unique_ptr<Module> M = getLazyModuleFromAssembly(
      Context, Mem, "define internal i32 @func() {\n"
                      "ret i32 0\n"
                    "}\n");

  EXPECT_FALSE(verifyModule(*M, &dbgs()));

  M->getFunction("func")->materialize();
  EXPECT_FALSE(M->getFunction("func")->empty());
  EXPECT_TRUE(M->getFunction("func")->getLinkage() ==
              GlobalValue::InternalLinkage);

  // Check that the linkage type is preserved after dematerialization.
  M->getFunction("func")->Dematerialize();
  EXPECT_TRUE(M->getFunction("func")->empty());
  EXPECT_TRUE(M->getFunction("func")->getLinkage() ==
              GlobalValue::InternalLinkage);
  EXPECT_FALSE(verifyModule(*M, &dbgs()));
}

TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677
  SmallString<1024> Mem;

  LLVMContext Context;
  std::unique_ptr<Module> M = getLazyModuleFromAssembly(
      Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"
                    "define void @func() {\n"
                    "  unreachable\n"
                    "bb:\n"
                    "  unreachable\n"
                    "}\n");
  EXPECT_FALSE(verifyModule(*M, &dbgs()));

  // Try (and fail) to dematerialize @func.
  M->getFunction("func")->Dematerialize();
  EXPECT_FALSE(M->getFunction("func")->empty());
}

TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {
  SmallString<1024> Mem;

  LLVMContext Context;
  std::unique_ptr<Module> M = getLazyModuleFromAssembly(
      Context, Mem, "define i8* @before() {\n"
                    "  ret i8* blockaddress(@func, %bb)\n"
                    "}\n"
                    "define void @other() {\n"
                    "  unreachable\n"
                    "}\n"
                    "define void @func() {\n"
                    "  unreachable\n"
                    "bb:\n"
                    "  unreachable\n"
                    "}\n");
  EXPECT_TRUE(M->getFunction("before")->empty());
  EXPECT_TRUE(M->getFunction("func")->empty());
  EXPECT_FALSE(verifyModule(*M, &dbgs()));

  // Materialize @before, pulling in @func.
  EXPECT_FALSE(M->getFunction("before")->materialize());
  EXPECT_FALSE(M->getFunction("func")->empty());
  EXPECT_TRUE(M->getFunction("other")->empty());
  EXPECT_FALSE(verifyModule(*M, &dbgs()));

  // Try (and fail) to dematerialize @func.
  M->getFunction("func")->Dematerialize();
  EXPECT_FALSE(M->getFunction("func")->empty());
  EXPECT_FALSE(verifyModule(*M, &dbgs()));
}

TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) {
  SmallString<1024> Mem;

  LLVMContext Context;
  std::unique_ptr<Module> M = getLazyModuleFromAssembly(
      Context, Mem, "define void @func() {\n"
                    "  unreachable\n"
                    "bb:\n"
                    "  unreachable\n"
                    "}\n"
                    "define void @other() {\n"
                    "  unreachable\n"
                    "}\n"
                    "define i8* @after() {\n"
                    "  ret i8* blockaddress(@func, %bb)\n"
                    "}\n");
  EXPECT_TRUE(M->getFunction("after")->empty());
  EXPECT_TRUE(M->getFunction("func")->empty());
  EXPECT_FALSE(verifyModule(*M, &dbgs()));

  // Materialize @after, pulling in @func.
  EXPECT_FALSE(M->getFunction("after")->materialize());
  EXPECT_FALSE(M->getFunction("func")->empty());
  EXPECT_TRUE(M->getFunction("other")->empty());
  EXPECT_FALSE(verifyModule(*M, &dbgs()));

  // Try (and fail) to dematerialize @func.
  M->getFunction("func")->Dematerialize();
  EXPECT_FALSE(M->getFunction("func")->empty());
  EXPECT_FALSE(verifyModule(*M, &dbgs()));
}

} // end namespace