Skip to content

Commit

Permalink
Move copying of global initializers below the cloning of functions.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
isanbard committed Nov 7, 2013
1 parent 9f47175 commit 5d5f2c3
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 5 deletions.
8 changes: 4 additions & 4 deletions lib/Linker/LinkModules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down
12 changes: 12 additions & 0 deletions unittests/Linker/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set(LLVM_LINK_COMPONENTS
core
linker
)

set(LinkerSources
LinkModulesTest.cpp
)

add_llvm_unittest(LinkerTests
${LinkerSources}
)
131 changes: 131 additions & 0 deletions unittests/Linker/LinkModulesTest.cpp
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions unittests/Linker/Makefile
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion unittests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 5d5f2c3

Please sign in to comment.