llvm/unittests/Bitcode/BitReaderTest.cpp
Teresa Johnson a547919737 Split Bitcode/ReaderWriter.h into separate reader and writer headers
Summary:
Split ReaderWriter.h which contains the APIs into both the BitReader and
BitWriter libraries into BitcodeReader.h and BitcodeWriter.h.

This is to address Chandler's concern about sharing the same API header
between multiple libraries (BitReader and BitWriter). That concern is
why we create a single bitcode library in our downstream build of clang,
which led to r286297 being reverted as it added a dependency that
created a cycle only when there is a single bitcode library (not two as
in upstream).

Reviewers: mehdi_amini

Subscribers: dlj, mehdi_amini, llvm-commits

Differential Revision: https://reviews.llvm.org/D26502

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286566 91177308-0d34-0410-b5e6-96231b3b80d8
2016-11-11 05:34:58 +00:00

197 lines
6.3 KiB
C++

//===- 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/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/BitstreamWriter.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/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
std::unique_ptr<Module> parseAssembly(LLVMContext &Context,
const char *Assembly) {
SMDiagnostic Error;
std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
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(Context, Assembly), Mem);
ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
getLazyBitcodeModule(MemoryBufferRef(Mem.str(), "test"), Context);
return std::move(ModuleOrErr.get());
}
// Tests that lazy evaluation can parse functions out of order.
TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
SmallString<1024> Mem;
LLVMContext Context;
std::unique_ptr<Module> M = getLazyModuleFromAssembly(
Context, Mem, "define void @f() {\n"
" unreachable\n"
"}\n"
"define void @g() {\n"
" unreachable\n"
"}\n"
"define void @h() {\n"
" unreachable\n"
"}\n"
"define void @j() {\n"
" unreachable\n"
"}\n");
EXPECT_FALSE(verifyModule(*M, &dbgs()));
Function *F = M->getFunction("f");
Function *G = M->getFunction("g");
Function *H = M->getFunction("h");
Function *J = M->getFunction("j");
// Initially all functions are not materialized (no basic blocks).
EXPECT_TRUE(F->empty());
EXPECT_TRUE(G->empty());
EXPECT_TRUE(H->empty());
EXPECT_TRUE(J->empty());
EXPECT_FALSE(verifyModule(*M, &dbgs()));
// Materialize h.
ASSERT_FALSE(H->materialize());
EXPECT_TRUE(F->empty());
EXPECT_TRUE(G->empty());
EXPECT_FALSE(H->empty());
EXPECT_TRUE(J->empty());
EXPECT_FALSE(verifyModule(*M, &dbgs()));
// Materialize g.
ASSERT_FALSE(G->materialize());
EXPECT_TRUE(F->empty());
EXPECT_FALSE(G->empty());
EXPECT_FALSE(H->empty());
EXPECT_TRUE(J->empty());
EXPECT_FALSE(verifyModule(*M, &dbgs()));
// Materialize j.
ASSERT_FALSE(J->materialize());
EXPECT_TRUE(F->empty());
EXPECT_FALSE(G->empty());
EXPECT_FALSE(H->empty());
EXPECT_FALSE(J->empty());
EXPECT_FALSE(verifyModule(*M, &dbgs()));
// Materialize f.
ASSERT_FALSE(F->materialize());
EXPECT_FALSE(F->empty());
EXPECT_FALSE(G->empty());
EXPECT_FALSE(H->empty());
EXPECT_FALSE(J->empty());
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()));
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()));
}
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()));
}
} // end namespace