[PATCH] D21255: Fix cloning GlobalValues with comdats across Modules.
Justin Lebar via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 13 10:25:53 PDT 2016
jlebar updated this revision to Diff 60556.
jlebar added a comment.
Preserve old behavior when a function isn't in a module.
Now all the tests pass. :)
http://reviews.llvm.org/D21255
Files:
lib/IR/Globals.cpp
unittests/IR/ValueTest.cpp
Index: unittests/IR/ValueTest.cpp
===================================================================
--- unittests/IR/ValueTest.cpp
+++ unittests/IR/ValueTest.cpp
@@ -89,6 +89,61 @@
EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1;
}
+TEST(GlobalTest, CloneWithComdatIntoSameModule) {
+ LLVMContext Ctx;
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+ auto M = make_unique<Module>("Module", Ctx);
+
+ GlobalVariable *GV1 =
+ new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty), "GV", nullptr,
+ GlobalVariable::NotThreadLocal, 1);
+ Comdat *Comdat = M->getOrInsertComdat("GV");
+ Comdat->setSelectionKind(Comdat::Largest);
+ GV1->setComdat(Comdat);
+
+ GlobalVariable *GV2 =
+ new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty), "GV", nullptr,
+ GlobalVariable::NotThreadLocal, 1);
+ GV2->copyAttributesFrom(GV1);
+ ASSERT_EQ(Comdat, GV1->getComdat());
+ ASSERT_TRUE(GV2->getComdat() != nullptr);
+ EXPECT_EQ(Comdat::Largest, GV2->getComdat()->getSelectionKind());
+
+ // GV1 and GV2 should share the same comdat pointers, because they're in the
+ // same module.
+ EXPECT_EQ(GV1->getComdat(), GV2->getComdat());
+}
+
+TEST(GlobalTest, CloneWithComdatIntoSeparateModule) {
+ LLVMContext Ctx;
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+ auto M1 = make_unique<Module>("Module1", Ctx);
+ auto M2 = make_unique<Module>("Module2", Ctx);
+
+ GlobalVariable *GV1 =
+ new GlobalVariable(*M1, Int32Ty, true, GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty), "GV", nullptr,
+ GlobalVariable::NotThreadLocal, 1);
+ Comdat *Comdat1 = M1->getOrInsertComdat("GV");
+ Comdat1->setSelectionKind(Comdat::Largest);
+ GV1->setComdat(Comdat1);
+
+ GlobalVariable *GV2 =
+ new GlobalVariable(*M2, Int32Ty, true, GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty), "GV", nullptr,
+ GlobalVariable::NotThreadLocal, 1);
+ GV2->copyAttributesFrom(GV1);
+ ASSERT_EQ(Comdat1, GV1->getComdat());
+ ASSERT_TRUE(GV2->getComdat() != nullptr);
+ EXPECT_EQ(Comdat::Largest, GV2->getComdat()->getSelectionKind());
+
+ // GV1 and GV2 cannot share the same comdat pointers, because they're in
+ // different Modules.
+ EXPECT_NE(GV1->getComdat(), GV2->getComdat());
+}
+
#ifdef GTEST_HAS_DEATH_TEST
#ifndef NDEBUG
TEST(GlobalTest, AlignDeath) {
Index: lib/IR/Globals.cpp
===================================================================
--- lib/IR/Globals.cpp
+++ lib/IR/Globals.cpp
@@ -96,7 +96,18 @@
if (const auto *GV = dyn_cast<GlobalObject>(Src)) {
setAlignment(GV->getAlignment());
setSection(GV->getSection());
- setComdat(const_cast<GlobalObject *>(GV)->getComdat());
+ // Src may not be in the same Module as this, and Modules own their Comdats,
+ // so we need to explicitly get a Comdat from our own Module. If we're not
+ // currently in a Module, guess that we're going to be put into the same
+ // module as Src, so it's safe to share Src's comdat.
+ Comdat *SrcComdat = const_cast<GlobalObject *>(GV)->getComdat();
+ if (SrcComdat == nullptr || getParent() == nullptr)
+ setComdat(SrcComdat);
+ else if (getParent() != nullptr) {
+ Comdat *C = getParent()->getOrInsertComdat(SrcComdat->getName());
+ C->setSelectionKind(SrcComdat->getSelectionKind());
+ setComdat(C);
+ }
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21255.60556.patch
Type: text/x-patch
Size: 3612 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160613/7b954e36/attachment.bin>
More information about the llvm-commits
mailing list