1 | //===- llvm/unittest/Linker/LinkModulesTest.cpp - IRBuilder tests ---------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm-c/Core.h" |
10 | #include "llvm-c/Linker.h" |
11 | #include "llvm/ADT/STLExtras.h" |
12 | #include "llvm/AsmParser/Parser.h" |
13 | #include "llvm/IR/BasicBlock.h" |
14 | #include "llvm/IR/DataLayout.h" |
15 | #include "llvm/IR/Function.h" |
16 | #include "llvm/IR/IRBuilder.h" |
17 | #include "llvm/IR/Module.h" |
18 | #include "llvm/Linker/Linker.h" |
19 | #include "llvm/Support/SourceMgr.h" |
20 | #include "gtest/gtest.h" |
21 | |
22 | using namespace llvm; |
23 | |
24 | namespace { |
25 | |
26 | class LinkModuleTest : public testing::Test { |
27 | protected: |
28 | void SetUp() override { |
29 | M.reset(p: new Module("MyModule" , Ctx)); |
30 | FunctionType *FTy = |
31 | FunctionType::get(Result: PointerType::getUnqual(C&: Ctx), Params: Type::getInt32Ty(C&: Ctx), |
32 | isVarArg: false /*=isVarArg*/); |
33 | F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "ba_func" , M: M.get()); |
34 | F->setCallingConv(CallingConv::C); |
35 | |
36 | EntryBB = BasicBlock::Create(Context&: Ctx, Name: "entry" , Parent: F); |
37 | SwitchCase1BB = BasicBlock::Create(Context&: Ctx, Name: "switch.case.1" , Parent: F); |
38 | SwitchCase2BB = BasicBlock::Create(Context&: Ctx, Name: "switch.case.2" , Parent: F); |
39 | ExitBB = BasicBlock::Create(Context&: Ctx, Name: "exit" , Parent: F); |
40 | |
41 | AT = ArrayType::get(ElementType: PointerType::getUnqual(C&: Ctx), NumElements: 3); |
42 | |
43 | GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/, |
44 | GlobalValue::InternalLinkage, nullptr,"switch.bas" ); |
45 | |
46 | // Global Initializer |
47 | std::vector<Constant *> Init; |
48 | Constant *SwitchCase1BA = BlockAddress::get(BB: SwitchCase1BB); |
49 | Init.push_back(x: SwitchCase1BA); |
50 | |
51 | Constant *SwitchCase2BA = BlockAddress::get(BB: SwitchCase2BB); |
52 | Init.push_back(x: SwitchCase2BA); |
53 | |
54 | ConstantInt *One = ConstantInt::get(Ty: Type::getInt32Ty(C&: Ctx), V: 1); |
55 | Constant *OnePtr = |
56 | ConstantExpr::getIntToPtr(C: One, Ty: PointerType::getUnqual(C&: Ctx)); |
57 | Init.push_back(x: OnePtr); |
58 | |
59 | GV->setInitializer(ConstantArray::get(T: AT, V: Init)); |
60 | } |
61 | |
62 | void TearDown() override { M.reset(); } |
63 | |
64 | LLVMContext Ctx; |
65 | std::unique_ptr<Module> M; |
66 | Function *F; |
67 | ArrayType *AT; |
68 | GlobalVariable *GV; |
69 | BasicBlock *EntryBB; |
70 | BasicBlock *SwitchCase1BB; |
71 | BasicBlock *SwitchCase2BB; |
72 | BasicBlock *ExitBB; |
73 | }; |
74 | |
75 | static void expectNoDiags(const DiagnosticInfo *DI, void *C) { |
76 | llvm_unreachable("expectNoDiags called!" ); |
77 | } |
78 | |
79 | TEST_F(LinkModuleTest, BlockAddress) { |
80 | IRBuilder<> Builder(EntryBB); |
81 | |
82 | std::vector<Value *> GEPIndices; |
83 | GEPIndices.push_back(x: ConstantInt::get(Ty: Type::getInt32Ty(C&: Ctx), V: 0)); |
84 | GEPIndices.push_back(x: &*F->arg_begin()); |
85 | |
86 | Value *GEP = Builder.CreateGEP(Ty: AT, Ptr: GV, IdxList: GEPIndices, Name: "switch.gep" ); |
87 | Value *Load = Builder.CreateLoad(Ty: AT->getElementType(), Ptr: GEP, Name: "switch.load" ); |
88 | |
89 | Builder.CreateRet(V: Load); |
90 | |
91 | Builder.SetInsertPoint(SwitchCase1BB); |
92 | Builder.CreateBr(Dest: ExitBB); |
93 | |
94 | Builder.SetInsertPoint(SwitchCase2BB); |
95 | Builder.CreateBr(Dest: ExitBB); |
96 | |
97 | Builder.SetInsertPoint(ExitBB); |
98 | Builder.CreateRet(V: ConstantPointerNull::get(T: PointerType::getUnqual(C&: Ctx))); |
99 | |
100 | Module *LinkedModule = new Module("MyModuleLinked" , Ctx); |
101 | Ctx.setDiagnosticHandlerCallBack(DiagHandler: expectNoDiags); |
102 | Linker::linkModules(Dest&: *LinkedModule, Src: std::move(M)); |
103 | |
104 | // Check that the global "@switch.bas" is well-formed. |
105 | const GlobalVariable *LinkedGV = LinkedModule->getNamedGlobal(Name: "switch.bas" ); |
106 | const Constant *Init = LinkedGV->getInitializer(); |
107 | |
108 | // @switch.bas = internal global [3 x i8*] |
109 | // [i8* blockaddress(@ba_func, %switch.case.1), |
110 | // i8* blockaddress(@ba_func, %switch.case.2), |
111 | // i8* inttoptr (i32 1 to i8*)] |
112 | |
113 | ArrayType *AT = ArrayType::get(ElementType: PointerType::getUnqual(C&: Ctx), NumElements: 3); |
114 | EXPECT_EQ(AT, Init->getType()); |
115 | |
116 | Value *Elem = Init->getOperand(i: 0); |
117 | ASSERT_TRUE(isa<BlockAddress>(Elem)); |
118 | EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), |
119 | LinkedModule->getFunction("ba_func" )); |
120 | EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), |
121 | LinkedModule->getFunction("ba_func" )); |
122 | |
123 | Elem = Init->getOperand(i: 1); |
124 | ASSERT_TRUE(isa<BlockAddress>(Elem)); |
125 | EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), |
126 | LinkedModule->getFunction("ba_func" )); |
127 | EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), |
128 | LinkedModule->getFunction("ba_func" )); |
129 | |
130 | delete LinkedModule; |
131 | } |
132 | |
133 | static Module *getExternal(LLVMContext &Ctx, StringRef FuncName) { |
134 | // Create a module with an empty externally-linked function |
135 | Module *M = new Module("ExternalModule" , Ctx); |
136 | FunctionType *FTy = FunctionType::get( |
137 | Result: Type::getVoidTy(C&: Ctx), Params: PointerType::getUnqual(C&: Ctx), isVarArg: false /*=isVarArgs*/); |
138 | |
139 | Function *F = |
140 | Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: FuncName, M); |
141 | F->setCallingConv(CallingConv::C); |
142 | |
143 | BasicBlock *BB = BasicBlock::Create(Context&: Ctx, Name: "" , Parent: F); |
144 | IRBuilder<> Builder(BB); |
145 | Builder.CreateRetVoid(); |
146 | return M; |
147 | } |
148 | |
149 | static Module *getInternal(LLVMContext &Ctx) { |
150 | Module *InternalM = new Module("InternalModule" , Ctx); |
151 | FunctionType *FTy = FunctionType::get( |
152 | Result: Type::getVoidTy(C&: Ctx), Params: PointerType::getUnqual(C&: Ctx), isVarArg: false /*=isVarArgs*/); |
153 | |
154 | Function *F = |
155 | Function::Create(Ty: FTy, Linkage: Function::InternalLinkage, N: "bar" , M: InternalM); |
156 | F->setCallingConv(CallingConv::C); |
157 | |
158 | BasicBlock *BB = BasicBlock::Create(Context&: Ctx, Name: "" , Parent: F); |
159 | IRBuilder<> Builder(BB); |
160 | Builder.CreateRetVoid(); |
161 | |
162 | StructType *STy = StructType::create(Context&: Ctx, Elements: PointerType::get(ElementType: FTy, AddressSpace: 0)); |
163 | |
164 | GlobalVariable *GV = |
165 | new GlobalVariable(*InternalM, STy, false /*=isConstant*/, |
166 | GlobalValue::InternalLinkage, nullptr, "g" ); |
167 | |
168 | GV->setInitializer(ConstantStruct::get(T: STy, Vs: F)); |
169 | return InternalM; |
170 | } |
171 | |
172 | TEST_F(LinkModuleTest, EmptyModule) { |
173 | std::unique_ptr<Module> InternalM(getInternal(Ctx)); |
174 | std::unique_ptr<Module> EmptyM(new Module("EmptyModule1" , Ctx)); |
175 | Ctx.setDiagnosticHandlerCallBack(DiagHandler: expectNoDiags); |
176 | Linker::linkModules(Dest&: *EmptyM, Src: std::move(InternalM)); |
177 | } |
178 | |
179 | TEST_F(LinkModuleTest, EmptyModule2) { |
180 | std::unique_ptr<Module> InternalM(getInternal(Ctx)); |
181 | std::unique_ptr<Module> EmptyM(new Module("EmptyModule1" , Ctx)); |
182 | Ctx.setDiagnosticHandlerCallBack(DiagHandler: expectNoDiags); |
183 | Linker::linkModules(Dest&: *InternalM, Src: std::move(EmptyM)); |
184 | } |
185 | |
186 | TEST_F(LinkModuleTest, TypeMerge) { |
187 | LLVMContext C; |
188 | SMDiagnostic Err; |
189 | |
190 | const char *M1Str = "%t = type {i32}\n" |
191 | "@t1 = weak global %t zeroinitializer\n" ; |
192 | std::unique_ptr<Module> M1 = parseAssemblyString(AsmString: M1Str, Err, Context&: C); |
193 | |
194 | const char *M2Str = "%t = type {i32}\n" |
195 | "@t2 = weak global %t zeroinitializer\n" ; |
196 | std::unique_ptr<Module> M2 = parseAssemblyString(AsmString: M2Str, Err, Context&: C); |
197 | |
198 | Ctx.setDiagnosticHandlerCallBack(DiagHandler: expectNoDiags); |
199 | Linker::linkModules(Dest&: *M1, Src: std::move(M2)); |
200 | |
201 | EXPECT_EQ(M1->getNamedGlobal("t1" )->getType(), |
202 | M1->getNamedGlobal("t2" )->getType()); |
203 | } |
204 | |
205 | TEST_F(LinkModuleTest, NewCAPISuccess) { |
206 | std::unique_ptr<Module> DestM(getExternal(Ctx, FuncName: "foo" )); |
207 | std::unique_ptr<Module> SourceM(getExternal(Ctx, FuncName: "bar" )); |
208 | LLVMBool Result = |
209 | LLVMLinkModules2(Dest: wrap(P: DestM.get()), Src: wrap(P: SourceM.release())); |
210 | EXPECT_EQ(0, Result); |
211 | // "bar" is present in destination module |
212 | EXPECT_NE(nullptr, DestM->getFunction("bar" )); |
213 | } |
214 | |
215 | static void diagnosticHandler(LLVMDiagnosticInfoRef DI, void *C) { |
216 | auto *Err = reinterpret_cast<std::string *>(C); |
217 | char *CErr = LLVMGetDiagInfoDescription(DI); |
218 | *Err = CErr; |
219 | LLVMDisposeMessage(Message: CErr); |
220 | } |
221 | |
222 | TEST_F(LinkModuleTest, NewCAPIFailure) { |
223 | // Symbol clash between two modules |
224 | LLVMContext Ctx; |
225 | std::string Err; |
226 | LLVMContextSetDiagnosticHandler(C: wrap(P: &Ctx), Handler: diagnosticHandler, DiagnosticContext: &Err); |
227 | |
228 | std::unique_ptr<Module> DestM(getExternal(Ctx, FuncName: "foo" )); |
229 | std::unique_ptr<Module> SourceM(getExternal(Ctx, FuncName: "foo" )); |
230 | LLVMBool Result = |
231 | LLVMLinkModules2(Dest: wrap(P: DestM.get()), Src: wrap(P: SourceM.release())); |
232 | EXPECT_EQ(1, Result); |
233 | EXPECT_EQ("Linking globals named 'foo': symbol multiply defined!" , Err); |
234 | } |
235 | |
236 | TEST_F(LinkModuleTest, MoveDistinctMDs) { |
237 | LLVMContext C; |
238 | SMDiagnostic Err; |
239 | |
240 | const char *SrcStr = "define void @foo() !attach !0 {\n" |
241 | "entry:\n" |
242 | " call void @llvm.md(metadata !1)\n" |
243 | " ret void, !attach !2\n" |
244 | "}\n" |
245 | "declare void @llvm.md(metadata)\n" |
246 | "!named = !{!3, !4}\n" |
247 | "!0 = distinct !{}\n" |
248 | "!1 = distinct !{}\n" |
249 | "!2 = distinct !{}\n" |
250 | "!3 = distinct !{}\n" |
251 | "!4 = !{!3}\n" ; |
252 | |
253 | std::unique_ptr<Module> Src = parseAssemblyString(AsmString: SrcStr, Err, Context&: C); |
254 | assert(Src); |
255 | ASSERT_TRUE(Src.get()); |
256 | |
257 | // Get the addresses of the Metadata before merging. |
258 | Function *F = &*Src->begin(); |
259 | ASSERT_EQ("foo" , F->getName()); |
260 | BasicBlock *BB = &F->getEntryBlock(); |
261 | auto *CI = cast<CallInst>(Val: &BB->front()); |
262 | auto *RI = cast<ReturnInst>(Val: BB->getTerminator()); |
263 | NamedMDNode *NMD = &*Src->named_metadata_begin(); |
264 | |
265 | MDNode *M0 = F->getMetadata(Kind: "attach" ); |
266 | MDNode *M1 = |
267 | cast<MDNode>(Val: cast<MetadataAsValue>(Val: CI->getArgOperand(i: 0))->getMetadata()); |
268 | MDNode *M2 = RI->getMetadata(Kind: "attach" ); |
269 | MDNode *M3 = NMD->getOperand(i: 0); |
270 | MDNode *M4 = NMD->getOperand(i: 1); |
271 | |
272 | // Confirm a few things about the IR. |
273 | EXPECT_TRUE(M0->isDistinct()); |
274 | EXPECT_TRUE(M1->isDistinct()); |
275 | EXPECT_TRUE(M2->isDistinct()); |
276 | EXPECT_TRUE(M3->isDistinct()); |
277 | EXPECT_TRUE(M4->isUniqued()); |
278 | EXPECT_EQ(M3, M4->getOperand(0)); |
279 | |
280 | // Link into destination module. |
281 | auto Dst = std::make_unique<Module>(args: "Linked" , args&: C); |
282 | ASSERT_TRUE(Dst.get()); |
283 | Ctx.setDiagnosticHandlerCallBack(DiagHandler: expectNoDiags); |
284 | Linker::linkModules(Dest&: *Dst, Src: std::move(Src)); |
285 | |
286 | // Check that distinct metadata was moved, not cloned. Even !4, the uniqued |
287 | // node, should effectively be moved, since its only operand hasn't changed. |
288 | F = &*Dst->begin(); |
289 | BB = &F->getEntryBlock(); |
290 | CI = cast<CallInst>(Val: &BB->front()); |
291 | RI = cast<ReturnInst>(Val: BB->getTerminator()); |
292 | NMD = &*Dst->named_metadata_begin(); |
293 | |
294 | EXPECT_EQ(M0, F->getMetadata("attach" )); |
295 | EXPECT_EQ(M1, cast<MetadataAsValue>(CI->getArgOperand(0))->getMetadata()); |
296 | EXPECT_EQ(M2, RI->getMetadata("attach" )); |
297 | EXPECT_EQ(M3, NMD->getOperand(0)); |
298 | EXPECT_EQ(M4, NMD->getOperand(1)); |
299 | |
300 | // Confirm a few things about the IR. This shouldn't have changed. |
301 | EXPECT_TRUE(M0->isDistinct()); |
302 | EXPECT_TRUE(M1->isDistinct()); |
303 | EXPECT_TRUE(M2->isDistinct()); |
304 | EXPECT_TRUE(M3->isDistinct()); |
305 | EXPECT_TRUE(M4->isUniqued()); |
306 | EXPECT_EQ(M3, M4->getOperand(0)); |
307 | } |
308 | |
309 | TEST_F(LinkModuleTest, RemangleIntrinsics) { |
310 | LLVMContext C; |
311 | SMDiagnostic Err; |
312 | |
313 | // We load two modules inside the same context C. In both modules there is a |
314 | // "struct.rtx_def" type. In the module loaded the second (Bar) this type will |
315 | // be renamed to "struct.rtx_def.0". Check that the intrinsics which have this |
316 | // type in the signature are properly remangled. |
317 | const char *FooStr = |
318 | "%struct.rtx_def = type { i16 }\n" |
319 | "define void @foo(%struct.rtx_def %a) {\n" |
320 | " call %struct.rtx_def @llvm.ssa.copy.s_struct.rtx_defs(%struct.rtx_def %a)\n" |
321 | " ret void\n" |
322 | "}\n" |
323 | "declare %struct.rtx_def @llvm.ssa.copy.s_struct.rtx_defs(%struct.rtx_def)\n" ; |
324 | |
325 | const char *BarStr = |
326 | "%struct.rtx_def = type { i16 }\n" |
327 | "define void @bar(%struct.rtx_def %a) {\n" |
328 | " call %struct.rtx_def @llvm.ssa.copy.s_struct.rtx_defs(%struct.rtx_def %a)\n" |
329 | " ret void\n" |
330 | "}\n" |
331 | "declare %struct.rtx_def @llvm.ssa.copy.s_struct.rtx_defs(%struct.rtx_def)\n" ; |
332 | |
333 | std::unique_ptr<Module> Foo = parseAssemblyString(AsmString: FooStr, Err, Context&: C); |
334 | assert(Foo); |
335 | ASSERT_TRUE(Foo.get()); |
336 | // Foo is loaded first, so the type and the intrinsic have theis original |
337 | // names. |
338 | ASSERT_TRUE(Foo->getFunction("llvm.ssa.copy.s_struct.rtx_defs" )); |
339 | ASSERT_FALSE(Foo->getFunction("llvm.ssa.copy.s_struct.rtx_defs.0" )); |
340 | |
341 | std::unique_ptr<Module> Bar = parseAssemblyString(AsmString: BarStr, Err, Context&: C); |
342 | assert(Bar); |
343 | ASSERT_TRUE(Bar.get()); |
344 | // Bar is loaded after Foo, so the type is renamed to struct.rtx_def.0. Check |
345 | // that the intrinsic is also renamed. |
346 | ASSERT_FALSE(Bar->getFunction("llvm.ssa.copy.s_struct.rtx_defs" )); |
347 | ASSERT_TRUE(Bar->getFunction("llvm.ssa.copy.s_struct.rtx_def.0s" )); |
348 | |
349 | // Link two modules together. |
350 | auto Dst = std::make_unique<Module>(args: "Linked" , args&: C); |
351 | ASSERT_TRUE(Dst.get()); |
352 | Ctx.setDiagnosticHandlerCallBack(DiagHandler: expectNoDiags); |
353 | bool Failed = Linker::linkModules(Dest&: *Foo, Src: std::move(Bar)); |
354 | ASSERT_FALSE(Failed); |
355 | |
356 | // "struct.rtx_def" from Foo and "struct.rtx_def.0" from Bar are isomorphic |
357 | // types, so they must be uniquified by linker. Check that they use the same |
358 | // intrinsic definition. |
359 | Function *F = Foo->getFunction(Name: "llvm.ssa.copy.s_struct.rtx_defs" ); |
360 | ASSERT_EQ(F->getNumUses(), (unsigned)2); |
361 | } |
362 | |
363 | } // end anonymous namespace |
364 | |