diff options
author | Bill Wendling <isanbard@gmail.com> | 2014-01-16 06:29:36 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2014-01-16 06:29:36 +0000 |
commit | a950ad4eec1b0ff3c1a83e9d8ccba9dc36995352 (patch) | |
tree | 270aa747069de45c560c0d1e6dd3d81f25808db6 /unittests | |
parent | fab01c190883724f92111e5bdb4d4d82748284eb (diff) | |
download | llvm-a950ad4eec1b0ff3c1a83e9d8ccba9dc36995352.tar.gz llvm-a950ad4eec1b0ff3c1a83e9d8ccba9dc36995352.tar.bz2 llvm-a950ad4eec1b0ff3c1a83e9d8ccba9dc36995352.tar.xz |
Reapply r194218 with fix:
Move copying of global initializers below the cloning of functions.
The BlockAddress doesn't have access to the correct basic blocks until the
functions have been cloned. This causes the BlockAddress to point to the old
values. Just wait until the functions have been cloned before copying the
initializers.
PR13163
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199354 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests')
-rw-r--r-- | unittests/Linker/CMakeLists.txt | 12 | ||||
-rw-r--r-- | unittests/Linker/LinkModulesTest.cpp | 165 | ||||
-rw-r--r-- | unittests/Linker/Makefile | 15 | ||||
-rw-r--r-- | unittests/Makefile | 2 |
4 files changed, 193 insertions, 1 deletions
diff --git a/unittests/Linker/CMakeLists.txt b/unittests/Linker/CMakeLists.txt new file mode 100644 index 0000000000..c3dccb6c7b --- /dev/null +++ b/unittests/Linker/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + core + linker + ) + +set(LinkerSources + LinkModulesTest.cpp + ) + +add_llvm_unittest(LinkerTests + ${LinkerSources} + ) diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp new file mode 100644 index 0000000000..c5942a1268 --- /dev/null +++ b/unittests/Linker/LinkModulesTest.cpp @@ -0,0 +1,165 @@ +//===- llvm/unittest/Linker/LinkModulesTest.cpp - IRBuilder tests ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Linker.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class LinkModuleTest : public testing::Test { +protected: + virtual void SetUp() { + LLVMContext &Ctx = getGlobalContext(); + M.reset(new Module("MyModule", Ctx)); + FunctionType *FTy = FunctionType::get(Type::getInt8PtrTy(Ctx), + Type::getInt32Ty(Ctx), + false /*=isVarArg*/); + F = Function::Create(FTy, Function::ExternalLinkage, "ba_func", M.get()); + F->setCallingConv(CallingConv::C); + + EntryBB = BasicBlock::Create(Ctx, "entry", F); + SwitchCase1BB = BasicBlock::Create(Ctx, "switch.case.1", F); + SwitchCase2BB = BasicBlock::Create(Ctx, "switch.case.2", F); + ExitBB = BasicBlock::Create(Ctx, "exit", F); + + ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3); + + GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/, + GlobalValue::InternalLinkage, + 0, "switch.bas"); + + + // Global Initializer + std::vector<Constant*> Init; + Constant *SwitchCase1BA = BlockAddress::get(SwitchCase1BB); + Init.push_back(SwitchCase1BA); + + Constant *SwitchCase2BA = BlockAddress::get(SwitchCase2BB); + Init.push_back(SwitchCase2BA); + + ConstantInt *One = ConstantInt::get(Type::getInt32Ty(Ctx), 1); + Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr, + One, Type::getInt8PtrTy(Ctx)); + Init.push_back(OnePtr); + + GV->setInitializer(ConstantArray::get(AT, Init)); + } + + virtual void TearDown() { + M.reset(); + } + + OwningPtr<Module> M; + Function *F; + GlobalVariable *GV; + BasicBlock *EntryBB; + BasicBlock *SwitchCase1BB; + BasicBlock *SwitchCase2BB; + BasicBlock *ExitBB; +}; + +TEST_F(LinkModuleTest, BlockAddress) { + LLVMContext &Ctx = getGlobalContext(); + IRBuilder<> Builder(EntryBB); + + std::vector<Value*> GEPIndices; + GEPIndices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0)); + GEPIndices.push_back(F->arg_begin()); + + Value *GEP = Builder.CreateGEP(GV, GEPIndices, "switch.gep"); + Value *Load = Builder.CreateLoad(GEP, "switch.load"); + + Builder.CreateRet(Load); + + Builder.SetInsertPoint(SwitchCase1BB); + Builder.CreateBr(ExitBB); + + Builder.SetInsertPoint(SwitchCase2BB); + Builder.CreateBr(ExitBB); + + Builder.SetInsertPoint(ExitBB); + Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx))); + + Module *LinkedModule = new Module("MyModuleLinked", getGlobalContext()); + Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, 0); + + // Delete the original module. + M.reset(); + + // Check that the global "@switch.bas" is well-formed. + const GlobalVariable *LinkedGV = LinkedModule->getNamedGlobal("switch.bas"); + const Constant *Init = LinkedGV->getInitializer(); + + // @switch.bas = internal global [3 x i8*] + // [i8* blockaddress(@ba_func, %switch.case.1), + // i8* blockaddress(@ba_func, %switch.case.2), + // i8* inttoptr (i32 1 to i8*)] + + ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3); + EXPECT_EQ(AT, Init->getType()); + + Value *Elem = Init->getOperand(0); + ASSERT_TRUE(isa<BlockAddress>(Elem)); + EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + Elem = Init->getOperand(1); + ASSERT_TRUE(isa<BlockAddress>(Elem)); + EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + delete LinkedModule; +} + +TEST_F(LinkModuleTest, EmptyModule) { + LLVMContext &Ctx = getGlobalContext(); + Module *InternalM = new Module("InternalModule", Ctx); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), + Type::getInt8PtrTy(Ctx), + false /*=isVarArgs*/); + + F = Function::Create(FTy, Function::InternalLinkage, "bar", InternalM); + F->setCallingConv(CallingConv::C); + + BasicBlock *BB = BasicBlock::Create(Ctx, "", F); + IRBuilder<> Builder(BB); + Builder.CreateRetVoid(); + + StructType *STy = StructType::create(Ctx, PointerType::get(FTy, 0)); + + GlobalVariable *GV = + new GlobalVariable(*InternalM, STy, false /*=isConstant*/, + GlobalValue::InternalLinkage, 0, "g"); + + GV->setInitializer(ConstantStruct::get(STy, F)); + + + Module *EmptyM = new Module("EmptyModule1", Ctx); + Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, 0); + + delete EmptyM; + EmptyM = new Module("EmptyModule2", Ctx); + Linker::LinkModules(InternalM, EmptyM, Linker::PreserveSource, 0); + + delete EmptyM; + delete InternalM; +} + +} // end anonymous namespace diff --git a/unittests/Linker/Makefile b/unittests/Linker/Makefile new file mode 100644 index 0000000000..c6058c4d60 --- /dev/null +++ b/unittests/Linker/Makefile @@ -0,0 +1,15 @@ +##===- unittests/Linker/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TESTNAME = Linker +LINK_COMPONENTS := core linker + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Makefile b/unittests/Makefile index 0f80814f98..dbef6cf9b3 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -10,7 +10,7 @@ LEVEL = .. PARALLEL_DIRS = ADT Analysis Bitcode CodeGen DebugInfo \ - ExecutionEngine IR MC Object Option Support Transforms + ExecutionEngine IR Linker MC Object Option Support Transforms include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest |