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