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
22 namespace llvm {
23 namespace {
24
TEST(VerifierTest,Branch_i1)25 TEST(VerifierTest, Branch_i1) {
26 LLVMContext C;
27 Module M("M", C);
28 FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
29 Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", M);
30 BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
31 BasicBlock *Exit = BasicBlock::Create(C, "exit", F);
32 ReturnInst::Create(C, 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(C);
38 BranchInst *BI = BranchInst::Create(Exit, Exit, False, Entry);
39
40 // ... then use setOperand to redirect it to a value of different type.
41
42 Constant *Zero32 = ConstantInt::get(IntegerType::get(C, 32), 0);
43 BI->setOperand(0, Zero32);
44
45 EXPECT_TRUE(verifyFunction(*F));
46 }
47
TEST(VerifierTest,Freeze)48 TEST(VerifierTest, Freeze) {
49 LLVMContext C;
50 Module M("M", C);
51 FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
52 Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", M);
53 BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
54 ReturnInst *RI = ReturnInst::Create(C, Entry);
55
56 IntegerType *ITy = IntegerType::get(C, 32);
57 ConstantInt *CI = ConstantInt::get(ITy, 0);
58
59 // Valid type : freeze(<2 x i32>)
60 Constant *CV = ConstantVector::getSplat(ElementCount::getFixed(2), CI);
61 FreezeInst *FI_vec = new FreezeInst(CV);
62 FI_vec->insertBefore(RI);
63
64 EXPECT_FALSE(verifyFunction(*F));
65
66 FI_vec->eraseFromParent();
67
68 // Valid type : freeze(float)
69 Constant *CFP = ConstantFP::get(Type::getDoubleTy(C), 0.0);
70 FreezeInst *FI_dbl = new FreezeInst(CFP);
71 FI_dbl->insertBefore(RI);
72
73 EXPECT_FALSE(verifyFunction(*F));
74
75 FI_dbl->eraseFromParent();
76
77 // Valid type : freeze(i32*)
78 PointerType *PT = PointerType::get(ITy, 0);
79 ConstantPointerNull *CPN = ConstantPointerNull::get(PT);
80 FreezeInst *FI_ptr = new FreezeInst(CPN);
81 FI_ptr->insertBefore(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(RI);
90
91 EXPECT_FALSE(verifyFunction(*F));
92
93 FI->eraseFromParent();
94 }
95
TEST(VerifierTest,InvalidRetAttribute)96 TEST(VerifierTest, InvalidRetAttribute) {
97 LLVMContext C;
98 Module M("M", C);
99 FunctionType *FTy = FunctionType::get(Type::getInt32Ty(C), /*isVarArg=*/false);
100 Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", M);
101 AttributeList AS = F->getAttributes();
102 F->setAttributes(
103 AS.addAttribute(C, AttributeList::ReturnIndex, Attribute::UWTable));
104
105 std::string Error;
106 raw_string_ostream ErrorOS(Error);
107 EXPECT_TRUE(verifyModule(M, &ErrorOS));
108 EXPECT_TRUE(StringRef(ErrorOS.str()).startswith(
109 "Attribute 'uwtable' only applies to functions!"));
110 }
111
TEST(VerifierTest,CrossModuleRef)112 TEST(VerifierTest, CrossModuleRef) {
113 LLVMContext C;
114 Module M1("M1", C);
115 Module M2("M2", C);
116 Module M3("M3", C);
117 FunctionType *FTy = FunctionType::get(Type::getInt32Ty(C), /*isVarArg=*/false);
118 Function *F1 = Function::Create(FTy, Function::ExternalLinkage, "foo1", M1);
119 Function *F2 = Function::Create(FTy, Function::ExternalLinkage, "foo2", M2);
120 Function *F3 = Function::Create(FTy, Function::ExternalLinkage, "foo3", M3);
121
122 BasicBlock *Entry1 = BasicBlock::Create(C, "entry", F1);
123 BasicBlock *Entry3 = BasicBlock::Create(C, "entry", F3);
124
125 // BAD: Referencing function in another module
126 CallInst::Create(F2,"call",Entry1);
127
128 // BAD: Referencing personality routine in another module
129 F3->setPersonalityFn(F2);
130
131 // Fill in the body
132 Constant *ConstZero = ConstantInt::get(Type::getInt32Ty(C), 0);
133 ReturnInst::Create(C, ConstZero, Entry1);
134 ReturnInst::Create(C, ConstZero, Entry3);
135
136 std::string Error;
137 raw_string_ostream ErrorOS(Error);
138 EXPECT_TRUE(verifyModule(M2, &ErrorOS));
139 EXPECT_TRUE(StringRef(ErrorOS.str())
140 .equals("Global is used by function in a different module\n"
141 "i32 ()* @foo2\n"
142 "; ModuleID = 'M2'\n"
143 "i32 ()* @foo3\n"
144 "; ModuleID = 'M3'\n"
145 "Global is referenced in a different module!\n"
146 "i32 ()* @foo2\n"
147 "; ModuleID = 'M2'\n"
148 " %call = call i32 @foo2()\n"
149 "i32 ()* @foo1\n"
150 "; ModuleID = 'M1'\n"));
151
152 Error.clear();
153 EXPECT_TRUE(verifyModule(M1, &ErrorOS));
154 EXPECT_TRUE(StringRef(ErrorOS.str()).equals(
155 "Referencing function in another module!\n"
156 " %call = call i32 @foo2()\n"
157 "; ModuleID = 'M1'\n"
158 "i32 ()* @foo2\n"
159 "; ModuleID = 'M2'\n"));
160
161 Error.clear();
162 EXPECT_TRUE(verifyModule(M3, &ErrorOS));
163 EXPECT_TRUE(StringRef(ErrorOS.str()).startswith(
164 "Referencing personality function in another module!"));
165
166 // Erase bad methods to avoid triggering an assertion failure on destruction
167 F1->eraseFromParent();
168 F3->eraseFromParent();
169 }
170
TEST(VerifierTest,InvalidVariableLinkage)171 TEST(VerifierTest, InvalidVariableLinkage) {
172 LLVMContext C;
173 Module M("M", C);
174 new GlobalVariable(M, Type::getInt8Ty(C), false,
175 GlobalValue::LinkOnceODRLinkage, nullptr, "Some Global");
176 std::string Error;
177 raw_string_ostream ErrorOS(Error);
178 EXPECT_TRUE(verifyModule(M, &ErrorOS));
179 EXPECT_TRUE(
180 StringRef(ErrorOS.str()).startswith("Global is external, but doesn't "
181 "have external or weak linkage!"));
182 }
183
TEST(VerifierTest,InvalidFunctionLinkage)184 TEST(VerifierTest, InvalidFunctionLinkage) {
185 LLVMContext C;
186 Module M("M", C);
187
188 FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
189 Function::Create(FTy, GlobalValue::LinkOnceODRLinkage, "foo", &M);
190 std::string Error;
191 raw_string_ostream ErrorOS(Error);
192 EXPECT_TRUE(verifyModule(M, &ErrorOS));
193 EXPECT_TRUE(
194 StringRef(ErrorOS.str()).startswith("Global is external, but doesn't "
195 "have external or weak linkage!"));
196 }
197
TEST(VerifierTest,DetectInvalidDebugInfo)198 TEST(VerifierTest, DetectInvalidDebugInfo) {
199 {
200 LLVMContext C;
201 Module M("M", C);
202 DIBuilder DIB(M);
203 DIB.createCompileUnit(dwarf::DW_LANG_C89, DIB.createFile("broken.c", "/"),
204 "unittest", false, "", 0);
205 DIB.finalize();
206 EXPECT_FALSE(verifyModule(M));
207
208 // Now break it by inserting non-CU node to the list of CUs.
209 auto *File = DIB.createFile("not-a-CU.f", ".");
210 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu");
211 NMD->addOperand(File);
212 EXPECT_TRUE(verifyModule(M));
213 }
214 {
215 LLVMContext C;
216 Module M("M", C);
217 DIBuilder DIB(M);
218 auto *CU = DIB.createCompileUnit(dwarf::DW_LANG_C89,
219 DIB.createFile("broken.c", "/"),
220 "unittest", false, "", 0);
221 new GlobalVariable(M, Type::getInt8Ty(C), false,
222 GlobalValue::ExternalLinkage, nullptr, "g");
223
224 auto *F = Function::Create(FunctionType::get(Type::getVoidTy(C), false),
225 Function::ExternalLinkage, "f", M);
226 IRBuilder<> Builder(BasicBlock::Create(C, "", F));
227 Builder.CreateUnreachable();
228 F->setSubprogram(DIB.createFunction(
229 CU, "f", "f", DIB.createFile("broken.c", "/"), 1, nullptr, 1,
230 DINode::FlagZero,
231 DISubprogram::SPFlagLocalToUnit | DISubprogram::SPFlagDefinition));
232 DIB.finalize();
233 EXPECT_FALSE(verifyModule(M));
234
235 // Now break it by not listing the CU at all.
236 M.eraseNamedMetadata(M.getOrInsertNamedMetadata("llvm.dbg.cu"));
237 EXPECT_TRUE(verifyModule(M));
238 }
239 }
240
241 } // end anonymous namespace
242 } // end namespace llvm
243