llvm-6502/unittests/Bitcode/BitReaderTest.cpp
Petar Jovanovic fd42335e83 Do not destroy external linkage when deleting function body
The function deleteBody() converts the linkage to external and thus destroys
original linkage type value. Lack of correct linkage type causes wrong
relocations to be emitted later.
Calling dropAllReferences() instead of deleteBody() will fix the issue.

Differential Revision: http://reviews.llvm.org/D5415


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218302 91177308-0d34-0410-b5e6-96231b3b80d8
2014-09-23 12:54:19 +00:00

168 lines
5.6 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/SmallString.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/AsmParser/Parser.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