Mark ThreadPool unittests as unsupported on PowerPC64
[oota-llvm.git] / unittests / Linker / LinkModulesTest.cpp
index ccbb89e41076021c23c428afd8043e4aa37075e5..ba8f4798172f25d893fc3cc1743a2f3b5a1e1cad 100644 (file)
@@ -7,12 +7,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Linker.h"
-#include "llvm/IR/IRBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Linker/Linker.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm-c/Linker.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -21,8 +25,7 @@ namespace {
 
 class LinkModuleTest : public testing::Test {
 protected:
-  virtual void SetUp() {
-    LLVMContext &Ctx = getGlobalContext();
+  void SetUp() override {
     M.reset(new Module("MyModule", Ctx));
     FunctionType *FTy = FunctionType::get(
         Type::getInt8PtrTy(Ctx), Type::getInt32Ty(Ctx), false /*=isVarArg*/);
@@ -34,10 +37,10 @@ protected:
     SwitchCase2BB = BasicBlock::Create(Ctx, "switch.case.2", F);
     ExitBB = BasicBlock::Create(Ctx, "exit", F);
 
-    ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3);
+    AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3);
 
     GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/,
-                            GlobalValue::InternalLinkage, 0, "switch.bas");
+                            GlobalValue::InternalLinkage, nullptr,"switch.bas");
 
     // Global Initializer
     std::vector<Constant *> Init;
@@ -55,10 +58,12 @@ protected:
     GV->setInitializer(ConstantArray::get(AT, Init));
   }
 
-  virtual void TearDown() { M.reset(); }
+  void TearDown() override { M.reset(); }
 
-  OwningPtr<Module> M;
+  LLVMContext Ctx;
+  std::unique_ptr<Module> M;
   Function *F;
+  ArrayType *AT;
   GlobalVariable *GV;
   BasicBlock *EntryBB;
   BasicBlock *SwitchCase1BB;
@@ -66,15 +71,18 @@ protected:
   BasicBlock *ExitBB;
 };
 
+static void expectNoDiags(const DiagnosticInfo &DI, void *C) {
+  EXPECT_TRUE(false);
+}
+
 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());
+  GEPIndices.push_back(&*F->arg_begin());
 
-  Value *GEP = Builder.CreateGEP(GV, GEPIndices, "switch.gep");
+  Value *GEP = Builder.CreateGEP(AT, GV, GEPIndices, "switch.gep");
   Value *Load = Builder.CreateLoad(GEP, "switch.load");
 
   Builder.CreateRet(Load);
@@ -88,8 +96,9 @@ TEST_F(LinkModuleTest, BlockAddress) {
   Builder.SetInsertPoint(ExitBB);
   Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx)));
 
-  Module *LinkedModule = new Module("MyModuleLinked", getGlobalContext());
-  Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, 0);
+  Module *LinkedModule = new Module("MyModuleLinked", Ctx);
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*LinkedModule, *M);
 
   // Delete the original module.
   M.reset();
@@ -123,4 +132,173 @@ TEST_F(LinkModuleTest, BlockAddress) {
   delete LinkedModule;
 }
 
+static Module *getExternal(LLVMContext &Ctx, StringRef FuncName) {
+  // Create a module with an empty externally-linked function
+  Module *M = new Module("ExternalModule", Ctx);
+  FunctionType *FTy = FunctionType::get(
+      Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/);
+
+  Function *F =
+      Function::Create(FTy, Function::ExternalLinkage, FuncName, M);
+  F->setCallingConv(CallingConv::C);
+
+  BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
+  IRBuilder<> Builder(BB);
+  Builder.CreateRetVoid();
+  return M;
+}
+
+static Module *getInternal(LLVMContext &Ctx) {
+  Module *InternalM = new Module("InternalModule", Ctx);
+  FunctionType *FTy = FunctionType::get(
+      Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/);
+
+  Function *F =
+      Function::Create(FTy, Function::InternalLinkage, "bar", InternalM);
+  F->setCallingConv(CallingConv::C);
+
+  BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
+  IRBuilder<> Builder(BB);
+  Builder.CreateRetVoid();
+
+  StructType *STy = StructType::create(Ctx, PointerType::get(FTy, 0));
+
+  GlobalVariable *GV =
+      new GlobalVariable(*InternalM, STy, false /*=isConstant*/,
+                         GlobalValue::InternalLinkage, nullptr, "g");
+
+  GV->setInitializer(ConstantStruct::get(STy, F));
+  return InternalM;
+}
+
+TEST_F(LinkModuleTest, EmptyModule) {
+  std::unique_ptr<Module> InternalM(getInternal(Ctx));
+  std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx));
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*EmptyM, *InternalM);
+}
+
+TEST_F(LinkModuleTest, EmptyModule2) {
+  std::unique_ptr<Module> InternalM(getInternal(Ctx));
+  std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx));
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*InternalM, *EmptyM);
+}
+
+TEST_F(LinkModuleTest, TypeMerge) {
+  LLVMContext C;
+  SMDiagnostic Err;
+
+  const char *M1Str = "%t = type {i32}\n"
+                      "@t1 = weak global %t zeroinitializer\n";
+  std::unique_ptr<Module> M1 = parseAssemblyString(M1Str, Err, C);
+
+  const char *M2Str = "%t = type {i32}\n"
+                      "@t2 = weak global %t zeroinitializer\n";
+  std::unique_ptr<Module> M2 = parseAssemblyString(M2Str, Err, C);
+
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*M1, *M2);
+
+  EXPECT_EQ(M1->getNamedGlobal("t1")->getType(),
+            M1->getNamedGlobal("t2")->getType());
+}
+
+TEST_F(LinkModuleTest, CAPISuccess) {
+  std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+  std::unique_ptr<Module> SourceM(getExternal(Ctx, "bar"));
+  char *errout = nullptr;
+  LLVMBool result = LLVMLinkModules(wrap(DestM.get()), wrap(SourceM.get()),
+                                    LLVMLinkerDestroySource, &errout);
+  EXPECT_EQ(0, result);
+  EXPECT_EQ(nullptr, errout);
+  // "bar" is present in destination module
+  EXPECT_NE(nullptr, DestM->getFunction("bar"));
+}
+
+TEST_F(LinkModuleTest, CAPIFailure) {
+  // Symbol clash between two modules
+  std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+  std::unique_ptr<Module> SourceM(getExternal(Ctx, "foo"));
+  char *errout = nullptr;
+  LLVMBool result = LLVMLinkModules(wrap(DestM.get()), wrap(SourceM.get()),
+                                    LLVMLinkerDestroySource, &errout);
+  EXPECT_EQ(1, result);
+  EXPECT_STREQ("Linking globals named 'foo': symbol multiply defined!", errout);
+  LLVMDisposeMessage(errout);
+}
+
+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<Module> 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<CallInst>(&BB->front());
+  auto *RI = cast<ReturnInst>(BB->getTerminator());
+  NamedMDNode *NMD = &*Src->named_metadata_begin();
+
+  MDNode *M0 = F->getMetadata("attach");
+  MDNode *M1 =
+      cast<MDNode>(cast<MetadataAsValue>(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<Module>("Linked", C);
+  ASSERT_TRUE(Dst.get());
+  Ctx.setDiagnosticHandler(expectNoDiags);
+  Linker::linkModules(*Dst, *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<CallInst>(&BB->front());
+  RI = cast<ReturnInst>(BB->getTerminator());
+  NMD = &*Dst->named_metadata_begin();
+
+  EXPECT_EQ(M0, F->getMetadata("attach"));
+  EXPECT_EQ(M1, cast<MetadataAsValue>(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