OSDN Git Service

Update aosp/master LLVM for rebase to r239765
[android-x86/external-llvm.git] / unittests / Linker / LinkModulesTest.cpp
1 //===- llvm/unittest/Linker/LinkModulesTest.cpp - IRBuilder tests ---------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/BasicBlock.h"
12 #include "llvm/IR/DataLayout.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/IRBuilder.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/Linker/Linker.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "llvm-c/Linker.h"
19 #include "gtest/gtest.h"
20
21 using namespace llvm;
22
23 namespace {
24
25 class LinkModuleTest : public testing::Test {
26 protected:
27   void SetUp() override {
28     M.reset(new Module("MyModule", Ctx));
29     FunctionType *FTy = FunctionType::get(
30         Type::getInt8PtrTy(Ctx), Type::getInt32Ty(Ctx), false /*=isVarArg*/);
31     F = Function::Create(FTy, Function::ExternalLinkage, "ba_func", M.get());
32     F->setCallingConv(CallingConv::C);
33
34     EntryBB = BasicBlock::Create(Ctx, "entry", F);
35     SwitchCase1BB = BasicBlock::Create(Ctx, "switch.case.1", F);
36     SwitchCase2BB = BasicBlock::Create(Ctx, "switch.case.2", F);
37     ExitBB = BasicBlock::Create(Ctx, "exit", F);
38
39     AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3);
40
41     GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/,
42                             GlobalValue::InternalLinkage, nullptr,"switch.bas");
43
44     // Global Initializer
45     std::vector<Constant *> Init;
46     Constant *SwitchCase1BA = BlockAddress::get(SwitchCase1BB);
47     Init.push_back(SwitchCase1BA);
48
49     Constant *SwitchCase2BA = BlockAddress::get(SwitchCase2BB);
50     Init.push_back(SwitchCase2BA);
51
52     ConstantInt *One = ConstantInt::get(Type::getInt32Ty(Ctx), 1);
53     Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr, One,
54                                              Type::getInt8PtrTy(Ctx));
55     Init.push_back(OnePtr);
56
57     GV->setInitializer(ConstantArray::get(AT, Init));
58   }
59
60   void TearDown() override { M.reset(); }
61
62   LLVMContext Ctx;
63   std::unique_ptr<Module> M;
64   Function *F;
65   ArrayType *AT;
66   GlobalVariable *GV;
67   BasicBlock *EntryBB;
68   BasicBlock *SwitchCase1BB;
69   BasicBlock *SwitchCase2BB;
70   BasicBlock *ExitBB;
71 };
72
73 TEST_F(LinkModuleTest, BlockAddress) {
74   IRBuilder<> Builder(EntryBB);
75
76   std::vector<Value *> GEPIndices;
77   GEPIndices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0));
78   GEPIndices.push_back(F->arg_begin());
79
80   Value *GEP = Builder.CreateGEP(AT, GV, GEPIndices, "switch.gep");
81   Value *Load = Builder.CreateLoad(GEP, "switch.load");
82
83   Builder.CreateRet(Load);
84
85   Builder.SetInsertPoint(SwitchCase1BB);
86   Builder.CreateBr(ExitBB);
87
88   Builder.SetInsertPoint(SwitchCase2BB);
89   Builder.CreateBr(ExitBB);
90
91   Builder.SetInsertPoint(ExitBB);
92   Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx)));
93
94   Module *LinkedModule = new Module("MyModuleLinked", Ctx);
95   Linker::LinkModules(LinkedModule, M.get());
96
97   // Delete the original module.
98   M.reset();
99
100   // Check that the global "@switch.bas" is well-formed.
101   const GlobalVariable *LinkedGV = LinkedModule->getNamedGlobal("switch.bas");
102   const Constant *Init = LinkedGV->getInitializer();
103
104   // @switch.bas = internal global [3 x i8*]
105   //   [i8* blockaddress(@ba_func, %switch.case.1),
106   //    i8* blockaddress(@ba_func, %switch.case.2),
107   //    i8* inttoptr (i32 1 to i8*)]
108
109   ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3);
110   EXPECT_EQ(AT, Init->getType());
111
112   Value *Elem = Init->getOperand(0);
113   ASSERT_TRUE(isa<BlockAddress>(Elem));
114   EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(),
115             LinkedModule->getFunction("ba_func"));
116   EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(),
117             LinkedModule->getFunction("ba_func"));
118
119   Elem = Init->getOperand(1);
120   ASSERT_TRUE(isa<BlockAddress>(Elem));
121   EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(),
122             LinkedModule->getFunction("ba_func"));
123   EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(),
124             LinkedModule->getFunction("ba_func"));
125
126   delete LinkedModule;
127 }
128
129 static Module *getExternal(LLVMContext &Ctx, StringRef FuncName) {
130   // Create a module with an empty externally-linked function
131   Module *M = new Module("ExternalModule", Ctx);
132   FunctionType *FTy = FunctionType::get(
133       Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/);
134
135   Function *F =
136       Function::Create(FTy, Function::ExternalLinkage, FuncName, M);
137   F->setCallingConv(CallingConv::C);
138
139   BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
140   IRBuilder<> Builder(BB);
141   Builder.CreateRetVoid();
142   return M;
143 }
144
145 static Module *getInternal(LLVMContext &Ctx) {
146   Module *InternalM = new Module("InternalModule", Ctx);
147   FunctionType *FTy = FunctionType::get(
148       Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/);
149
150   Function *F =
151       Function::Create(FTy, Function::InternalLinkage, "bar", InternalM);
152   F->setCallingConv(CallingConv::C);
153
154   BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
155   IRBuilder<> Builder(BB);
156   Builder.CreateRetVoid();
157
158   StructType *STy = StructType::create(Ctx, PointerType::get(FTy, 0));
159
160   GlobalVariable *GV =
161       new GlobalVariable(*InternalM, STy, false /*=isConstant*/,
162                          GlobalValue::InternalLinkage, nullptr, "g");
163
164   GV->setInitializer(ConstantStruct::get(STy, F));
165   return InternalM;
166 }
167
168 TEST_F(LinkModuleTest, EmptyModule) {
169   std::unique_ptr<Module> InternalM(getInternal(Ctx));
170   std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx));
171   Linker::LinkModules(EmptyM.get(), InternalM.get());
172 }
173
174 TEST_F(LinkModuleTest, EmptyModule2) {
175   std::unique_ptr<Module> InternalM(getInternal(Ctx));
176   std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx));
177   Linker::LinkModules(InternalM.get(), EmptyM.get());
178 }
179
180 TEST_F(LinkModuleTest, TypeMerge) {
181   LLVMContext C;
182   SMDiagnostic Err;
183
184   const char *M1Str = "%t = type {i32}\n"
185                       "@t1 = weak global %t zeroinitializer\n";
186   std::unique_ptr<Module> M1 = parseAssemblyString(M1Str, Err, C);
187
188   const char *M2Str = "%t = type {i32}\n"
189                       "@t2 = weak global %t zeroinitializer\n";
190   std::unique_ptr<Module> M2 = parseAssemblyString(M2Str, Err, C);
191
192   Linker::LinkModules(M1.get(), M2.get(), [](const llvm::DiagnosticInfo &){});
193
194   EXPECT_EQ(M1->getNamedGlobal("t1")->getType(),
195             M1->getNamedGlobal("t2")->getType());
196 }
197
198 TEST_F(LinkModuleTest, CAPISuccess) {
199   std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
200   std::unique_ptr<Module> SourceM(getExternal(Ctx, "bar"));
201   char *errout = nullptr;
202   LLVMBool result = LLVMLinkModules(wrap(DestM.get()), wrap(SourceM.get()),
203                                     LLVMLinkerDestroySource, &errout);
204   EXPECT_EQ(0, result);
205   EXPECT_EQ(nullptr, errout);
206   // "bar" is present in destination module
207   EXPECT_NE(nullptr, DestM->getFunction("bar"));
208 }
209
210 TEST_F(LinkModuleTest, CAPIFailure) {
211   // Symbol clash between two modules
212   std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
213   std::unique_ptr<Module> SourceM(getExternal(Ctx, "foo"));
214   char *errout = nullptr;
215   LLVMBool result = LLVMLinkModules(wrap(DestM.get()), wrap(SourceM.get()),
216                                     LLVMLinkerDestroySource, &errout);
217   EXPECT_EQ(1, result);
218   EXPECT_STREQ("Linking globals named 'foo': symbol multiply defined!", errout);
219   LLVMDisposeMessage(errout);
220 }
221
222 } // end anonymous namespace