X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=unittests%2FLinker%2FLinkModulesTest.cpp;h=322a44f8aafe5d03fd6d3d0fdd51a72465e783a4;hb=71d29c18dce9d4bd7c35a902eb51152331bebec0;hp=58a3e72f63e9cc2f9937321695c2d63664d96e06;hpb=21a987d1ac00aa7100a7abd48896c944475775c7;p=oota-llvm.git diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp index 58a3e72f63e..322a44f8aaf 100644 --- a/unittests/Linker/LinkModulesTest.cpp +++ b/unittests/Linker/LinkModulesTest.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/STLExtras.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" @@ -15,6 +16,7 @@ #include "llvm/IR/Module.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/SourceMgr.h" +#include "llvm-c/Core.h" #include "llvm-c/Linker.h" #include "gtest/gtest.h" @@ -70,12 +72,16 @@ protected: BasicBlock *ExitBB; }; +static void expectNoDiags(const DiagnosticInfo &DI, void *C) { + EXPECT_TRUE(false); +} + TEST_F(LinkModuleTest, BlockAddress) { IRBuilder<> Builder(EntryBB); std::vector GEPIndices; GEPIndices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0)); - GEPIndices.push_back(F->arg_begin()); + GEPIndices.push_back(&*F->arg_begin()); Value *GEP = Builder.CreateGEP(AT, GV, GEPIndices, "switch.gep"); Value *Load = Builder.CreateLoad(GEP, "switch.load"); @@ -92,10 +98,8 @@ TEST_F(LinkModuleTest, BlockAddress) { Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx))); Module *LinkedModule = new Module("MyModuleLinked", Ctx); - Linker::LinkModules(LinkedModule, M.get()); - - // Delete the original module. - M.reset(); + Ctx.setDiagnosticHandler(expectNoDiags); + Linker::linkModules(*LinkedModule, std::move(M)); // Check that the global "@switch.bas" is well-formed. const GlobalVariable *LinkedGV = LinkedModule->getNamedGlobal("switch.bas"); @@ -168,13 +172,15 @@ static Module *getInternal(LLVMContext &Ctx) { TEST_F(LinkModuleTest, EmptyModule) { std::unique_ptr InternalM(getInternal(Ctx)); std::unique_ptr EmptyM(new Module("EmptyModule1", Ctx)); - Linker::LinkModules(EmptyM.get(), InternalM.get()); + Ctx.setDiagnosticHandler(expectNoDiags); + Linker::linkModules(*EmptyM, std::move(InternalM)); } TEST_F(LinkModuleTest, EmptyModule2) { std::unique_ptr InternalM(getInternal(Ctx)); std::unique_ptr EmptyM(new Module("EmptyModule1", Ctx)); - Linker::LinkModules(InternalM.get(), EmptyM.get()); + Ctx.setDiagnosticHandler(expectNoDiags); + Linker::linkModules(*InternalM, std::move(EmptyM)); } TEST_F(LinkModuleTest, TypeMerge) { @@ -189,7 +195,8 @@ TEST_F(LinkModuleTest, TypeMerge) { "@t2 = weak global %t zeroinitializer\n"; std::unique_ptr M2 = parseAssemblyString(M2Str, Err, C); - Linker::LinkModules(M1.get(), M2.get(), [](const llvm::DiagnosticInfo &){}); + Ctx.setDiagnosticHandler(expectNoDiags); + Linker::linkModules(*M1, std::move(M2)); EXPECT_EQ(M1->getNamedGlobal("t1")->getType(), M1->getNamedGlobal("t2")->getType()); @@ -216,6 +223,111 @@ TEST_F(LinkModuleTest, CAPIFailure) { LLVMLinkerDestroySource, &errout); EXPECT_EQ(1, result); EXPECT_STREQ("Linking globals named 'foo': symbol multiply defined!", errout); + LLVMDisposeMessage(errout); +} + +TEST_F(LinkModuleTest, NewCAPISuccess) { + std::unique_ptr DestM(getExternal(Ctx, "foo")); + std::unique_ptr SourceM(getExternal(Ctx, "bar")); + LLVMBool Result = + LLVMLinkModules2(wrap(DestM.get()), wrap(SourceM.release())); + EXPECT_EQ(0, Result); + // "bar" is present in destination module + EXPECT_NE(nullptr, DestM->getFunction("bar")); +} + +static void diagnosticHandler(LLVMDiagnosticInfoRef DI, void *C) { + auto *Err = reinterpret_cast(C); + char *CErr = LLVMGetDiagInfoDescription(DI); + *Err = CErr; + LLVMDisposeMessage(CErr); +} + +TEST_F(LinkModuleTest, NewCAPIFailure) { + // Symbol clash between two modules + LLVMContext Ctx; + std::string Err; + LLVMContextSetDiagnosticHandler(wrap(&Ctx), diagnosticHandler, &Err); + + std::unique_ptr DestM(getExternal(Ctx, "foo")); + std::unique_ptr SourceM(getExternal(Ctx, "foo")); + LLVMBool Result = + LLVMLinkModules2(wrap(DestM.get()), wrap(SourceM.release())); + EXPECT_EQ(1, Result); + EXPECT_EQ("Linking globals named 'foo': symbol multiply defined!", Err); +} + +TEST_F(LinkModuleTest, MoveDistinctMDs) { + LLVMContext C; + SMDiagnostic Err; + + const char *SrcStr = "define void @foo() !attach !0 {\n" + "entry:\n" + " call void @llvm.md(metadata !1)\n" + " ret void, !attach !2\n" + "}\n" + "declare void @llvm.md(metadata)\n" + "!named = !{!3, !4}\n" + "!0 = distinct !{}\n" + "!1 = distinct !{}\n" + "!2 = distinct !{}\n" + "!3 = distinct !{}\n" + "!4 = !{!3}\n"; + + std::unique_ptr Src = parseAssemblyString(SrcStr, Err, C); + assert(Src); + ASSERT_TRUE(Src.get()); + + // Get the addresses of the Metadata before merging. + Function *F = &*Src->begin(); + ASSERT_EQ("foo", F->getName()); + BasicBlock *BB = &F->getEntryBlock(); + auto *CI = cast(&BB->front()); + auto *RI = cast(BB->getTerminator()); + NamedMDNode *NMD = &*Src->named_metadata_begin(); + + MDNode *M0 = F->getMetadata("attach"); + MDNode *M1 = + cast(cast(CI->getArgOperand(0))->getMetadata()); + MDNode *M2 = RI->getMetadata("attach"); + MDNode *M3 = NMD->getOperand(0); + MDNode *M4 = NMD->getOperand(1); + + // Confirm a few things about the IR. + EXPECT_TRUE(M0->isDistinct()); + EXPECT_TRUE(M1->isDistinct()); + EXPECT_TRUE(M2->isDistinct()); + EXPECT_TRUE(M3->isDistinct()); + EXPECT_TRUE(M4->isUniqued()); + EXPECT_EQ(M3, M4->getOperand(0)); + + // Link into destination module. + auto Dst = llvm::make_unique("Linked", C); + ASSERT_TRUE(Dst.get()); + Ctx.setDiagnosticHandler(expectNoDiags); + Linker::linkModules(*Dst, std::move(Src)); + + // Check that distinct metadata was moved, not cloned. Even !4, the uniqued + // node, should effectively be moved, since its only operand hasn't changed. + F = &*Dst->begin(); + BB = &F->getEntryBlock(); + CI = cast(&BB->front()); + RI = cast(BB->getTerminator()); + NMD = &*Dst->named_metadata_begin(); + + EXPECT_EQ(M0, F->getMetadata("attach")); + EXPECT_EQ(M1, cast(CI->getArgOperand(0))->getMetadata()); + EXPECT_EQ(M2, RI->getMetadata("attach")); + EXPECT_EQ(M3, NMD->getOperand(0)); + EXPECT_EQ(M4, NMD->getOperand(1)); + + // Confirm a few things about the IR. This shouldn't have changed. + EXPECT_TRUE(M0->isDistinct()); + EXPECT_TRUE(M1->isDistinct()); + EXPECT_TRUE(M2->isDistinct()); + EXPECT_TRUE(M3->isDistinct()); + EXPECT_TRUE(M4->isUniqued()); + EXPECT_EQ(M3, M4->getOperand(0)); } } // end anonymous namespace