brintos

brintos / llvm-project-archived public Read only

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