aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2013-11-07 20:14:51 +0000
committerBill Wendling <isanbard@gmail.com>2013-11-07 20:14:51 +0000
commit5d5f2c37d57276c9320dd2677d355d47fa4bc5c4 (patch)
treec4c7a106e12d0d23238c5450cb84ec511c914fd5
parent9f471750fa6f34120d4758d5d14f54f899e34a54 (diff)
downloadexternal_llvm-5d5f2c37d57276c9320dd2677d355d47fa4bc5c4.zip
external_llvm-5d5f2c37d57276c9320dd2677d355d47fa4bc5c4.tar.gz
external_llvm-5d5f2c37d57276c9320dd2677d355d47fa4bc5c4.tar.bz2
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
-rw-r--r--lib/Linker/LinkModules.cpp8
-rw-r--r--unittests/Linker/CMakeLists.txt12
-rw-r--r--unittests/Linker/LinkModulesTest.cpp131
-rw-r--r--unittests/Linker/Makefile15
-rw-r--r--unittests/Makefile2
5 files changed, 163 insertions, 5 deletions
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index 8f2200e..00c2ed1 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -1251,10 +1251,6 @@ bool ModuleLinker::run() {
for (unsigned i = 0, e = AppendingVars.size(); i != e; ++i)
linkAppendingVarInit(AppendingVars[i]);
- // Update the initializers in the DstM module now that all globals that may
- // be referenced are in DstM.
- linkGlobalInits();
-
// Link in the function bodies that are defined in the source module into
// DstM.
for (Module::iterator SF = SrcM->begin(), E = SrcM->end(); SF != E; ++SF) {
@@ -1336,6 +1332,10 @@ bool ModuleLinker::run() {
}
} while (LinkedInAnyFunctions);
+ // Update the initializers in the DstM module now that all globals that may
+ // be referenced are in DstM.
+ linkGlobalInits();
+
// Now that all of the types from the source are used, resolve any structs
// copied over to the dest that didn't exist there.
TypeMap.linkDefinedTypeBodies();
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<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;
+}
+
+} // 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