1//===- llvm/unittest/IR/VerifierTest.cpp - Verifier unit tests --*- C++ -*-===//
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/IR/Verifier.h"
10#include "llvm/IR/Constants.h"
11#include "llvm/IR/DIBuilder.h"
12#include "llvm/IR/DerivedTypes.h"
13#include "llvm/IR/Function.h"
14#include "llvm/IR/GlobalAlias.h"
15#include "llvm/IR/GlobalVariable.h"
16#include "llvm/IR/IRBuilder.h"
17#include "llvm/IR/Instructions.h"
18#include "llvm/IR/LLVMContext.h"
19#include "llvm/IR/Module.h"
20#include "gtest/gtest.h"
21
22namespace llvm {
23namespace {
24
25TEST(VerifierTest, Branch_i1) {
26 LLVMContext C;
27 Module M("M", C);
28 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C), /*isVarArg=*/false);
29 Function *F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo", M);
30 BasicBlock *Entry = BasicBlock::Create(Context&: C, Name: "entry", Parent: F);
31 BasicBlock *Exit = BasicBlock::Create(Context&: C, Name: "exit", Parent: F);
32 ReturnInst::Create(C, InsertAtEnd: Exit);
33
34 // To avoid triggering an assertion in BranchInst::Create, we first create
35 // a branch with an 'i1' condition ...
36
37 Constant *False = ConstantInt::getFalse(Context&: C);
38 BranchInst *BI = BranchInst::Create(IfTrue: Exit, IfFalse: Exit, Cond: False, InsertAtEnd: Entry);
39
40 // ... then use setOperand to redirect it to a value of different type.
41
42 Constant *Zero32 = ConstantInt::get(Ty: IntegerType::get(C, NumBits: 32), V: 0);
43 BI->setOperand(i_nocapture: 0, Val_nocapture: Zero32);
44
45 EXPECT_TRUE(verifyFunction(*F));
46}
47
48TEST(VerifierTest, Freeze) {
49 LLVMContext C;
50 Module M("M", C);
51 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C), /*isVarArg=*/false);
52 Function *F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo", M);
53 BasicBlock *Entry = BasicBlock::Create(Context&: C, Name: "entry", Parent: F);
54 ReturnInst *RI = ReturnInst::Create(C, InsertAtEnd: Entry);
55
56 IntegerType *ITy = IntegerType::get(C, NumBits: 32);
57 ConstantInt *CI = ConstantInt::get(Ty: ITy, V: 0);
58
59 // Valid type : freeze(<2 x i32>)
60 Constant *CV = ConstantVector::getSplat(EC: ElementCount::getFixed(MinVal: 2), Elt: CI);
61 FreezeInst *FI_vec = new FreezeInst(CV);
62 FI_vec->insertBefore(InsertPos: RI);
63
64 EXPECT_FALSE(verifyFunction(*F));
65
66 FI_vec->eraseFromParent();
67
68 // Valid type : freeze(float)
69 Constant *CFP = ConstantFP::get(Ty: Type::getDoubleTy(C), V: 0.0);
70 FreezeInst *FI_dbl = new FreezeInst(CFP);
71 FI_dbl->insertBefore(InsertPos: RI);
72
73 EXPECT_FALSE(verifyFunction(*F));
74
75 FI_dbl->eraseFromParent();
76
77 // Valid type : freeze(i32*)
78 PointerType *PT = PointerType::get(ElementType: ITy, AddressSpace: 0);
79 ConstantPointerNull *CPN = ConstantPointerNull::get(T: PT);
80 FreezeInst *FI_ptr = new FreezeInst(CPN);
81 FI_ptr->insertBefore(InsertPos: RI);
82
83 EXPECT_FALSE(verifyFunction(*F));
84
85 FI_ptr->eraseFromParent();
86
87 // Valid type : freeze(int)
88 FreezeInst *FI = new FreezeInst(CI);
89 FI->insertBefore(InsertPos: RI);
90
91 EXPECT_FALSE(verifyFunction(*F));
92
93 FI->eraseFromParent();
94}
95
96TEST(VerifierTest, InvalidRetAttribute) {
97 LLVMContext C;
98 Module M("M", C);
99 FunctionType *FTy = FunctionType::get(Result: Type::getInt32Ty(C), /*isVarArg=*/false);
100 Function *F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo", M);
101 AttributeList AS = F->getAttributes();
102 F->setAttributes(AS.addRetAttribute(
103 C, Attr: Attribute::getWithUWTableKind(Context&: C, Kind: UWTableKind::Default)));
104
105 std::string Error;
106 raw_string_ostream ErrorOS(Error);
107 EXPECT_TRUE(verifyModule(M, &ErrorOS));
108 EXPECT_TRUE(
109 StringRef(ErrorOS.str())
110 .starts_with(
111 "Attribute 'uwtable' does not apply to function return values"));
112}
113
114/// Test the verifier rejects invalid nofpclass values that the assembler may
115/// also choose to reject.
116TEST(VerifierTest, InvalidNoFPClassAttribute) {
117 LLVMContext C;
118
119 const unsigned InvalidMasks[] = {0, fcAllFlags + 1};
120
121 for (unsigned InvalidMask : InvalidMasks) {
122 Module M("M", C);
123 FunctionType *FTy =
124 FunctionType::get(Result: Type::getFloatTy(C), /*isVarArg=*/false);
125 Function *F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo", M);
126 AttributeList AS = F->getAttributes();
127
128 // Don't use getWithNoFPClass to avoid using out of bounds enum values here.
129 F->setAttributes(AS.addRetAttribute(
130 C, Attribute::get(C, Attribute::NoFPClass, InvalidMask)));
131
132 std::string Error;
133 raw_string_ostream ErrorOS(Error);
134 EXPECT_TRUE(verifyModule(M, &ErrorOS));
135
136 StringRef ErrMsg(ErrorOS.str());
137
138 if (InvalidMask == 0) {
139 EXPECT_TRUE(ErrMsg.starts_with(
140 "Attribute 'nofpclass' must have at least one test bit set"))
141 << ErrMsg;
142 } else {
143 EXPECT_TRUE(ErrMsg.starts_with("Invalid value for 'nofpclass' test mask"))
144 << ErrMsg;
145 }
146 }
147}
148
149TEST(VerifierTest, CrossModuleRef) {
150 LLVMContext C;
151 Module M1("M1", C);
152 Module M2("M2", C);
153 Module M3("M3", C);
154 FunctionType *FTy = FunctionType::get(Result: Type::getInt32Ty(C), /*isVarArg=*/false);
155 Function *F1 = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo1", M&: M1);
156 Function *F2 = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo2", M&: M2);
157 Function *F3 = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo3", M&: M3);
158
159 BasicBlock *Entry1 = BasicBlock::Create(Context&: C, Name: "entry", Parent: F1);
160 BasicBlock *Entry3 = BasicBlock::Create(Context&: C, Name: "entry", Parent: F3);
161
162 // BAD: Referencing function in another module
163 CallInst::Create(Func: F2,NameStr: "call",InsertAtEnd: Entry1);
164
165 // BAD: Referencing personality routine in another module
166 F3->setPersonalityFn(F2);
167
168 // Fill in the body
169 Constant *ConstZero = ConstantInt::get(Ty: Type::getInt32Ty(C), V: 0);
170 ReturnInst::Create(C, retVal: ConstZero, InsertAtEnd: Entry1);
171 ReturnInst::Create(C, retVal: ConstZero, InsertAtEnd: Entry3);
172
173 std::string Error;
174 raw_string_ostream ErrorOS(Error);
175 EXPECT_TRUE(verifyModule(M2, &ErrorOS));
176 EXPECT_TRUE(StringRef(ErrorOS.str())
177 .equals("Global is referenced in a different module!\n"
178 "ptr @foo2\n"
179 "; ModuleID = 'M2'\n"
180 " %call = call i32 @foo2()\n"
181 "ptr @foo1\n"
182 "; ModuleID = 'M1'\n"
183 "Global is used by function in a different module\n"
184 "ptr @foo2\n"
185 "; ModuleID = 'M2'\n"
186 "ptr @foo3\n"
187 "; ModuleID = 'M3'\n"));
188
189 Error.clear();
190 EXPECT_TRUE(verifyModule(M1, &ErrorOS));
191 EXPECT_TRUE(StringRef(ErrorOS.str()).equals(
192 "Referencing function in another module!\n"
193 " %call = call i32 @foo2()\n"
194 "; ModuleID = 'M1'\n"
195 "ptr @foo2\n"
196 "; ModuleID = 'M2'\n"));
197
198 Error.clear();
199 EXPECT_TRUE(verifyModule(M3, &ErrorOS));
200 EXPECT_TRUE(
201 StringRef(ErrorOS.str())
202 .starts_with("Referencing personality function in another module!"));
203
204 // Erase bad methods to avoid triggering an assertion failure on destruction
205 F1->eraseFromParent();
206 F3->eraseFromParent();
207}
208
209TEST(VerifierTest, InvalidVariableLinkage) {
210 LLVMContext C;
211 Module M("M", C);
212 new GlobalVariable(M, Type::getInt8Ty(C), false,
213 GlobalValue::LinkOnceODRLinkage, nullptr, "Some Global");
214 std::string Error;
215 raw_string_ostream ErrorOS(Error);
216 EXPECT_TRUE(verifyModule(M, &ErrorOS));
217 EXPECT_TRUE(StringRef(ErrorOS.str())
218 .starts_with("Global is external, but doesn't "
219 "have external or weak linkage!"));
220}
221
222TEST(VerifierTest, InvalidFunctionLinkage) {
223 LLVMContext C;
224 Module M("M", C);
225
226 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C), /*isVarArg=*/false);
227 Function::Create(Ty: FTy, Linkage: GlobalValue::LinkOnceODRLinkage, N: "foo", M: &M);
228 std::string Error;
229 raw_string_ostream ErrorOS(Error);
230 EXPECT_TRUE(verifyModule(M, &ErrorOS));
231 EXPECT_TRUE(StringRef(ErrorOS.str())
232 .starts_with("Global is external, but doesn't "
233 "have external or weak linkage!"));
234}
235
236TEST(VerifierTest, DetectInvalidDebugInfo) {
237 {
238 LLVMContext C;
239 Module M("M", C);
240 DIBuilder DIB(M);
241 DIB.createCompileUnit(Lang: dwarf::DW_LANG_C89, File: DIB.createFile(Filename: "broken.c", Directory: "/"),
242 Producer: "unittest", isOptimized: false, Flags: "", RV: 0);
243 DIB.finalize();
244 EXPECT_FALSE(verifyModule(M));
245
246 // Now break it by inserting non-CU node to the list of CUs.
247 auto *File = DIB.createFile(Filename: "not-a-CU.f", Directory: ".");
248 NamedMDNode *NMD = M.getOrInsertNamedMetadata(Name: "llvm.dbg.cu");
249 NMD->addOperand(M: File);
250 EXPECT_TRUE(verifyModule(M));
251 }
252 {
253 LLVMContext C;
254 Module M("M", C);
255 DIBuilder DIB(M);
256 auto *CU = DIB.createCompileUnit(Lang: dwarf::DW_LANG_C89,
257 File: DIB.createFile(Filename: "broken.c", Directory: "/"),
258 Producer: "unittest", isOptimized: false, Flags: "", RV: 0);
259 new GlobalVariable(M, Type::getInt8Ty(C), false,
260 GlobalValue::ExternalLinkage, nullptr, "g");
261
262 auto *F = Function::Create(Ty: FunctionType::get(Result: Type::getVoidTy(C), isVarArg: false),
263 Linkage: Function::ExternalLinkage, N: "f", M);
264 IRBuilder<> Builder(BasicBlock::Create(Context&: C, Name: "", Parent: F));
265 Builder.CreateUnreachable();
266 F->setSubprogram(DIB.createFunction(
267 Scope: CU, Name: "f", LinkageName: "f", File: DIB.createFile(Filename: "broken.c", Directory: "/"), LineNo: 1, Ty: nullptr, ScopeLine: 1,
268 Flags: DINode::FlagZero,
269 SPFlags: DISubprogram::SPFlagLocalToUnit | DISubprogram::SPFlagDefinition));
270 DIB.finalize();
271 EXPECT_FALSE(verifyModule(M));
272
273 // Now break it by not listing the CU at all.
274 M.eraseNamedMetadata(NMD: M.getOrInsertNamedMetadata(Name: "llvm.dbg.cu"));
275 EXPECT_TRUE(verifyModule(M));
276 }
277}
278
279TEST(VerifierTest, MDNodeWrongContext) {
280 LLVMContext C1, C2;
281 auto *Node = MDNode::get(Context&: C1, MDs: std::nullopt);
282
283 Module M("M", C2);
284 auto *NamedNode = M.getOrInsertNamedMetadata(Name: "test");
285 NamedNode->addOperand(M: Node);
286
287 std::string Error;
288 raw_string_ostream ErrorOS(Error);
289 EXPECT_TRUE(verifyModule(M, &ErrorOS));
290 EXPECT_TRUE(
291 StringRef(ErrorOS.str())
292 .starts_with("MDNode context does not match Module context!"));
293}
294
295TEST(VerifierTest, AttributesWrongContext) {
296 LLVMContext C1, C2;
297 Module M1("M", C1);
298 FunctionType *FTy1 =
299 FunctionType::get(Result: Type::getVoidTy(C&: C1), /*isVarArg=*/false);
300 Function *F1 = Function::Create(Ty: FTy1, Linkage: Function::ExternalLinkage, N: "foo", M&: M1);
301 F1->setDoesNotReturn();
302
303 Module M2("M", C2);
304 FunctionType *FTy2 =
305 FunctionType::get(Result: Type::getVoidTy(C&: C2), /*isVarArg=*/false);
306 Function *F2 = Function::Create(Ty: FTy2, Linkage: Function::ExternalLinkage, N: "foo", M&: M2);
307 F2->copyAttributesFrom(Src: F1);
308
309 EXPECT_TRUE(verifyFunction(*F2));
310}
311
312TEST(VerifierTest, SwitchInst) {
313 LLVMContext C;
314 Module M("M", C);
315 IntegerType *Int32Ty = Type::getInt32Ty(C);
316 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C), Params: {Int32Ty, Int32Ty},
317 /*isVarArg=*/false);
318 Function *F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo", M);
319 BasicBlock *Entry = BasicBlock::Create(Context&: C, Name: "entry", Parent: F);
320 BasicBlock *Default = BasicBlock::Create(Context&: C, Name: "default", Parent: F);
321 BasicBlock *OnOne = BasicBlock::Create(Context&: C, Name: "on_one", Parent: F);
322 BasicBlock *OnTwo = BasicBlock::Create(Context&: C, Name: "on_two", Parent: F);
323
324 BasicBlock *Exit = BasicBlock::Create(Context&: C, Name: "exit", Parent: F);
325
326 BranchInst::Create(IfTrue: Exit, InsertAtEnd: Default);
327 BranchInst::Create(IfTrue: Exit, InsertAtEnd: OnTwo);
328 BranchInst::Create(IfTrue: Exit, InsertAtEnd: OnOne);
329 ReturnInst::Create(C, InsertAtEnd: Exit);
330
331 Value *Cond = F->getArg(i: 0);
332 SwitchInst *Switch = SwitchInst::Create(Value: Cond, Default, NumCases: 2, InsertAtEnd: Entry);
333 Switch->addCase(OnVal: ConstantInt::get(Ty: Int32Ty, V: 1), Dest: OnOne);
334 Switch->addCase(OnVal: ConstantInt::get(Ty: Int32Ty, V: 2), Dest: OnTwo);
335
336 EXPECT_FALSE(verifyFunction(*F));
337 // set one case value to function argument.
338 Switch->setOperand(i_nocapture: 2, Val_nocapture: F->getArg(i: 1));
339 EXPECT_TRUE(verifyFunction(*F));
340}
341
342TEST(VerifierTest, CrossFunctionRef) {
343 LLVMContext C;
344 Module M("M", C);
345 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C), /*isVarArg=*/false);
346 Function *F1 = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo1", M);
347 Function *F2 = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo2", M);
348 BasicBlock *Entry1 = BasicBlock::Create(Context&: C, Name: "entry", Parent: F1);
349 BasicBlock *Entry2 = BasicBlock::Create(Context&: C, Name: "entry", Parent: F2);
350 Type *I32 = Type::getInt32Ty(C);
351
352 Value *Alloca = new AllocaInst(I32, 0, "alloca", Entry1);
353 ReturnInst::Create(C, InsertAtEnd: Entry1);
354
355 Instruction *Store = new StoreInst(ConstantInt::get(Ty: I32, V: 0), Alloca, Entry2);
356 ReturnInst::Create(C, InsertAtEnd: Entry2);
357
358 std::string Error;
359 raw_string_ostream ErrorOS(Error);
360 EXPECT_TRUE(verifyModule(M, &ErrorOS));
361 EXPECT_TRUE(
362 StringRef(ErrorOS.str())
363 .starts_with("Referring to an instruction in another function!"));
364
365 // Explicitly erase the store to avoid a use-after-free when the module is
366 // destroyed.
367 Store->eraseFromParent();
368}
369
370TEST(VerifierTest, AtomicRMW) {
371 LLVMContext C;
372 Module M("M", C);
373 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C), /*isVarArg=*/false);
374 Function *F = Function::Create(Ty: FTy, Linkage: Function::ExternalLinkage, N: "foo", M);
375 BasicBlock *Entry = BasicBlock::Create(Context&: C, Name: "entry", Parent: F);
376 Value *Ptr = PoisonValue::get(T: PointerType::get(C, AddressSpace: 0));
377
378 Type *FPTy = Type::getFloatTy(C);
379 Constant *CF = ConstantFP::getZero(Ty: FPTy);
380
381 // Invalid scalable type : atomicrmw (<vscale x 2 x float>)
382 Constant *CV = ConstantVector::getSplat(EC: ElementCount::getScalable(MinVal: 2), Elt: CF);
383 new AtomicRMWInst(AtomicRMWInst::FAdd, Ptr, CV, Align(8),
384 AtomicOrdering::SequentiallyConsistent, SyncScope::System,
385 Entry);
386 ReturnInst::Create(C, InsertAtEnd: Entry);
387
388 std::string Error;
389 raw_string_ostream ErrorOS(Error);
390 EXPECT_TRUE(verifyFunction(*F, &ErrorOS));
391 EXPECT_TRUE(
392 StringRef(ErrorOS.str())
393 .starts_with("atomicrmw fadd operand must have floating-point or "
394 "fixed vector of floating-point type!"))
395 << ErrorOS.str();
396}
397
398} // end anonymous namespace
399} // end namespace llvm
400

source code of llvm/unittests/IR/VerifierTest.cpp