From 5d5f2c37d57276c9320dd2677d355d47fa4bc5c4 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 7 Nov 2013 20:14:51 +0000 Subject: 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@194218 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Linker/CMakeLists.txt | 12 ++++ unittests/Linker/LinkModulesTest.cpp | 131 +++++++++++++++++++++++++++++++++++ unittests/Linker/Makefile | 15 ++++ unittests/Makefile | 2 +- 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 unittests/Linker/CMakeLists.txt create mode 100644 unittests/Linker/LinkModulesTest.cpp create mode 100644 unittests/Linker/Makefile (limited to 'unittests') diff --git a/unittests/Linker/CMakeLists.txt b/unittests/Linker/CMakeLists.txt new file mode 100644 index 0000000..c3dccb6 --- /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 0000000..9d2d84d --- /dev/null +++ b/unittests/Linker/LinkModulesTest.cpp @@ -0,0 +1,131 @@ +//===- 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 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 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 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(Elem)); + EXPECT_EQ(cast(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + Elem = Init->getOperand(1); + ASSERT_TRUE(isa(Elem)); + EXPECT_EQ(cast(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + delete LinkedModule; +} + +} // end anonymous namespace diff --git a/unittests/Linker/Makefile b/unittests/Linker/Makefile new file mode 100644 index 0000000..c6058c4 --- /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 06ba932..fc7e780 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 + Linker MC Object Option Support Transforms include $(LEVEL)/Makefile.common -- cgit v1.1