10b57cec5SDimitry Andric //===-- Lint.cpp - Check for common errors in LLVM IR ---------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass statically checks for common and easily-identified constructs 100b57cec5SDimitry Andric // which produce undefined or likely unintended behavior in LLVM IR. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // It is not a guarantee of correctness, in two ways. First, it isn't 130b57cec5SDimitry Andric // comprehensive. There are checks which could be done statically which are 140b57cec5SDimitry Andric // not yet implemented. Some of these are indicated by TODO comments, but 150b57cec5SDimitry Andric // those aren't comprehensive either. Second, many conditions cannot be 160b57cec5SDimitry Andric // checked statically. This pass does no dynamic instrumentation, so it 170b57cec5SDimitry Andric // can't check for all possible problems. 180b57cec5SDimitry Andric // 190b57cec5SDimitry Andric // Another limitation is that it assumes all code will be executed. A store 200b57cec5SDimitry Andric // through a null pointer in a basic block which is never reached is harmless, 210b57cec5SDimitry Andric // but this pass will warn about it anyway. This is the main reason why most 220b57cec5SDimitry Andric // of these checks live here instead of in the Verifier pass. 230b57cec5SDimitry Andric // 240b57cec5SDimitry Andric // Optimization passes may make conditions that this pass checks for more or 250b57cec5SDimitry Andric // less obvious. If an optimization pass appears to be introducing a warning, 260b57cec5SDimitry Andric // it may be that the optimization pass is merely exposing an existing 270b57cec5SDimitry Andric // condition in the code. 280b57cec5SDimitry Andric // 290b57cec5SDimitry Andric // This code may be run before instcombine. In many cases, instcombine checks 300b57cec5SDimitry Andric // for the same kinds of things and turns instructions with undefined behavior 310b57cec5SDimitry Andric // into unreachable (or equivalent). Because of this, this pass makes some 320b57cec5SDimitry Andric // effort to look through bitcasts and so on. 330b57cec5SDimitry Andric // 340b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric #include "llvm/Analysis/Lint.h" 370b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 380b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 390b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 400b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 410b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 420b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 4306c3fb27SDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h" 440b57cec5SDimitry Andric #include "llvm/Analysis/ConstantFolding.h" 450b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h" 460b57cec5SDimitry Andric #include "llvm/Analysis/Loads.h" 470b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h" 4806c3fb27SDimitry Andric #include "llvm/Analysis/ScopedNoAliasAA.h" 490b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 5006c3fb27SDimitry Andric #include "llvm/Analysis/TypeBasedAliasAnalysis.h" 510b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 520b57cec5SDimitry Andric #include "llvm/IR/Argument.h" 530b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 540b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 550b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 560b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 570b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 580b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 590b57cec5SDimitry Andric #include "llvm/IR/Function.h" 600b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 610b57cec5SDimitry Andric #include "llvm/IR/InstVisitor.h" 620b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 630b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 640b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 650b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 660b57cec5SDimitry Andric #include "llvm/IR/Module.h" 67e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h" 680b57cec5SDimitry Andric #include "llvm/IR/Type.h" 690b57cec5SDimitry Andric #include "llvm/IR/Value.h" 700b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 710b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h" 720b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 730b57cec5SDimitry Andric #include <cassert> 740b57cec5SDimitry Andric #include <cstdint> 750b57cec5SDimitry Andric #include <iterator> 760b57cec5SDimitry Andric #include <string> 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric using namespace llvm; 790b57cec5SDimitry Andric 80*0fca6ea1SDimitry Andric static const char LintAbortOnErrorArgName[] = "lint-abort-on-error"; 81*0fca6ea1SDimitry Andric static cl::opt<bool> 82*0fca6ea1SDimitry Andric LintAbortOnError(LintAbortOnErrorArgName, cl::init(false), 83*0fca6ea1SDimitry Andric cl::desc("In the Lint pass, abort on errors.")); 84*0fca6ea1SDimitry Andric 850b57cec5SDimitry Andric namespace { 860b57cec5SDimitry Andric namespace MemRef { 870b57cec5SDimitry Andric static const unsigned Read = 1; 880b57cec5SDimitry Andric static const unsigned Write = 2; 890b57cec5SDimitry Andric static const unsigned Callee = 4; 900b57cec5SDimitry Andric static const unsigned Branchee = 8; 910b57cec5SDimitry Andric } // end namespace MemRef 920b57cec5SDimitry Andric 93e8d8bef9SDimitry Andric class Lint : public InstVisitor<Lint> { 940b57cec5SDimitry Andric friend class InstVisitor<Lint>; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric void visitFunction(Function &F); 970b57cec5SDimitry Andric 985ffd83dbSDimitry Andric void visitCallBase(CallBase &CB); 99e8d8bef9SDimitry Andric void visitMemoryReference(Instruction &I, const MemoryLocation &Loc, 1005ffd83dbSDimitry Andric MaybeAlign Alignment, Type *Ty, unsigned Flags); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric void visitReturnInst(ReturnInst &I); 1030b57cec5SDimitry Andric void visitLoadInst(LoadInst &I); 1040b57cec5SDimitry Andric void visitStoreInst(StoreInst &I); 1050b57cec5SDimitry Andric void visitXor(BinaryOperator &I); 1060b57cec5SDimitry Andric void visitSub(BinaryOperator &I); 1070b57cec5SDimitry Andric void visitLShr(BinaryOperator &I); 1080b57cec5SDimitry Andric void visitAShr(BinaryOperator &I); 1090b57cec5SDimitry Andric void visitShl(BinaryOperator &I); 1100b57cec5SDimitry Andric void visitSDiv(BinaryOperator &I); 1110b57cec5SDimitry Andric void visitUDiv(BinaryOperator &I); 1120b57cec5SDimitry Andric void visitSRem(BinaryOperator &I); 1130b57cec5SDimitry Andric void visitURem(BinaryOperator &I); 1140b57cec5SDimitry Andric void visitAllocaInst(AllocaInst &I); 1150b57cec5SDimitry Andric void visitVAArgInst(VAArgInst &I); 1160b57cec5SDimitry Andric void visitIndirectBrInst(IndirectBrInst &I); 1170b57cec5SDimitry Andric void visitExtractElementInst(ExtractElementInst &I); 1180b57cec5SDimitry Andric void visitInsertElementInst(InsertElementInst &I); 1190b57cec5SDimitry Andric void visitUnreachableInst(UnreachableInst &I); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric Value *findValue(Value *V, bool OffsetOk) const; 1220b57cec5SDimitry Andric Value *findValueImpl(Value *V, bool OffsetOk, 1230b57cec5SDimitry Andric SmallPtrSetImpl<Value *> &Visited) const; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric public: 1260b57cec5SDimitry Andric Module *Mod; 1270b57cec5SDimitry Andric const DataLayout *DL; 1280b57cec5SDimitry Andric AliasAnalysis *AA; 1290b57cec5SDimitry Andric AssumptionCache *AC; 1300b57cec5SDimitry Andric DominatorTree *DT; 1310b57cec5SDimitry Andric TargetLibraryInfo *TLI; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric std::string Messages; 1340b57cec5SDimitry Andric raw_string_ostream MessagesStr; 1350b57cec5SDimitry Andric 136e8d8bef9SDimitry Andric Lint(Module *Mod, const DataLayout *DL, AliasAnalysis *AA, 137e8d8bef9SDimitry Andric AssumptionCache *AC, DominatorTree *DT, TargetLibraryInfo *TLI) 138e8d8bef9SDimitry Andric : Mod(Mod), DL(DL), AA(AA), AC(AC), DT(DT), TLI(TLI), 139e8d8bef9SDimitry Andric MessagesStr(Messages) {} 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric void WriteValues(ArrayRef<const Value *> Vs) { 1420b57cec5SDimitry Andric for (const Value *V : Vs) { 1430b57cec5SDimitry Andric if (!V) 1440b57cec5SDimitry Andric continue; 1450b57cec5SDimitry Andric if (isa<Instruction>(V)) { 1460b57cec5SDimitry Andric MessagesStr << *V << '\n'; 1470b57cec5SDimitry Andric } else { 1480b57cec5SDimitry Andric V->printAsOperand(MessagesStr, true, Mod); 1490b57cec5SDimitry Andric MessagesStr << '\n'; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric /// A check failed, so printout out the condition and the message. 1550b57cec5SDimitry Andric /// 1560b57cec5SDimitry Andric /// This provides a nice place to put a breakpoint if you want to see why 1570b57cec5SDimitry Andric /// something is not correct. 1580b57cec5SDimitry Andric void CheckFailed(const Twine &Message) { MessagesStr << Message << '\n'; } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric /// A check failed (with values to print). 1610b57cec5SDimitry Andric /// 1620b57cec5SDimitry Andric /// This calls the Message-only version so that the above is easier to set 1630b57cec5SDimitry Andric /// a breakpoint on. 1640b57cec5SDimitry Andric template <typename T1, typename... Ts> 1650b57cec5SDimitry Andric void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { 1660b57cec5SDimitry Andric CheckFailed(Message); 1670b57cec5SDimitry Andric WriteValues({V1, Vs...}); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric }; 1700b57cec5SDimitry Andric } // end anonymous namespace 1710b57cec5SDimitry Andric 17281ad6265SDimitry Andric // Check - We know that cond should be true, if not print an error message. 17381ad6265SDimitry Andric #define Check(C, ...) \ 174e8d8bef9SDimitry Andric do { \ 175e8d8bef9SDimitry Andric if (!(C)) { \ 176e8d8bef9SDimitry Andric CheckFailed(__VA_ARGS__); \ 177e8d8bef9SDimitry Andric return; \ 178e8d8bef9SDimitry Andric } \ 179e8d8bef9SDimitry Andric } while (false) 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric void Lint::visitFunction(Function &F) { 1820b57cec5SDimitry Andric // This isn't undefined behavior, it's just a little unusual, and it's a 1830b57cec5SDimitry Andric // fairly common mistake to neglect to name a function. 18481ad6265SDimitry Andric Check(F.hasName() || F.hasLocalLinkage(), 1850b57cec5SDimitry Andric "Unusual: Unnamed function with non-local linkage", &F); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric // TODO: Check for irreducible control flow. 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1905ffd83dbSDimitry Andric void Lint::visitCallBase(CallBase &I) { 1915ffd83dbSDimitry Andric Value *Callee = I.getCalledOperand(); 1920b57cec5SDimitry Andric 193bdd1243dSDimitry Andric visitMemoryReference(I, MemoryLocation::getAfter(Callee), std::nullopt, 194bdd1243dSDimitry Andric nullptr, MemRef::Callee); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric if (Function *F = dyn_cast<Function>(findValue(Callee, 1970b57cec5SDimitry Andric /*OffsetOk=*/false))) { 19881ad6265SDimitry Andric Check(I.getCallingConv() == F->getCallingConv(), 1990b57cec5SDimitry Andric "Undefined behavior: Caller and callee calling convention differ", 2000b57cec5SDimitry Andric &I); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric FunctionType *FT = F->getFunctionType(); 2035ffd83dbSDimitry Andric unsigned NumActualArgs = I.arg_size(); 2040b57cec5SDimitry Andric 20581ad6265SDimitry Andric Check(FT->isVarArg() ? FT->getNumParams() <= NumActualArgs 2060b57cec5SDimitry Andric : FT->getNumParams() == NumActualArgs, 2070b57cec5SDimitry Andric "Undefined behavior: Call argument count mismatches callee " 2080b57cec5SDimitry Andric "argument count", 2090b57cec5SDimitry Andric &I); 2100b57cec5SDimitry Andric 21181ad6265SDimitry Andric Check(FT->getReturnType() == I.getType(), 2120b57cec5SDimitry Andric "Undefined behavior: Call return type mismatches " 2130b57cec5SDimitry Andric "callee return type", 2140b57cec5SDimitry Andric &I); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // Check argument types (in case the callee was casted) and attributes. 2170b57cec5SDimitry Andric // TODO: Verify that caller and callee attributes are compatible. 2180b57cec5SDimitry Andric Function::arg_iterator PI = F->arg_begin(), PE = F->arg_end(); 2195ffd83dbSDimitry Andric auto AI = I.arg_begin(), AE = I.arg_end(); 2200b57cec5SDimitry Andric for (; AI != AE; ++AI) { 2210b57cec5SDimitry Andric Value *Actual = *AI; 2220b57cec5SDimitry Andric if (PI != PE) { 2230b57cec5SDimitry Andric Argument *Formal = &*PI++; 22481ad6265SDimitry Andric Check(Formal->getType() == Actual->getType(), 2250b57cec5SDimitry Andric "Undefined behavior: Call argument type mismatches " 2260b57cec5SDimitry Andric "callee parameter type", 2270b57cec5SDimitry Andric &I); 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric // Check that noalias arguments don't alias other arguments. This is 2300b57cec5SDimitry Andric // not fully precise because we don't know the sizes of the dereferenced 2310b57cec5SDimitry Andric // memory regions. 2320b57cec5SDimitry Andric if (Formal->hasNoAliasAttr() && Actual->getType()->isPointerTy()) { 2335ffd83dbSDimitry Andric AttributeList PAL = I.getAttributes(); 2340b57cec5SDimitry Andric unsigned ArgNo = 0; 235fcaf7f86SDimitry Andric for (auto *BI = I.arg_begin(); BI != AE; ++BI, ++ArgNo) { 2360b57cec5SDimitry Andric // Skip ByVal arguments since they will be memcpy'd to the callee's 2370b57cec5SDimitry Andric // stack so we're not really passing the pointer anyway. 238349cc55cSDimitry Andric if (PAL.hasParamAttr(ArgNo, Attribute::ByVal)) 2390b57cec5SDimitry Andric continue; 2400b57cec5SDimitry Andric // If both arguments are readonly, they have no dependence. 2415ffd83dbSDimitry Andric if (Formal->onlyReadsMemory() && I.onlyReadsMemory(ArgNo)) 2420b57cec5SDimitry Andric continue; 2435f757f3fSDimitry Andric // Skip readnone arguments since those are guaranteed not to be 2445f757f3fSDimitry Andric // dereferenced anyway. 2455f757f3fSDimitry Andric if (I.doesNotAccessMemory(ArgNo)) 2465f757f3fSDimitry Andric continue; 2470b57cec5SDimitry Andric if (AI != BI && (*BI)->getType()->isPointerTy()) { 2480b57cec5SDimitry Andric AliasResult Result = AA->alias(*AI, *BI); 24981ad6265SDimitry Andric Check(Result != AliasResult::MustAlias && 250fe6060f1SDimitry Andric Result != AliasResult::PartialAlias, 2510b57cec5SDimitry Andric "Unusual: noalias argument aliases another argument", &I); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric // Check that an sret argument points to valid memory. 2570b57cec5SDimitry Andric if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) { 258e8d8bef9SDimitry Andric Type *Ty = Formal->getParamStructRetType(); 259e8d8bef9SDimitry Andric MemoryLocation Loc( 260e8d8bef9SDimitry Andric Actual, LocationSize::precise(DL->getTypeStoreSize(Ty))); 261e8d8bef9SDimitry Andric visitMemoryReference(I, Loc, DL->getABITypeAlign(Ty), Ty, 2620b57cec5SDimitry Andric MemRef::Read | MemRef::Write); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric 2685ffd83dbSDimitry Andric if (const auto *CI = dyn_cast<CallInst>(&I)) { 2690b57cec5SDimitry Andric if (CI->isTailCall()) { 2700b57cec5SDimitry Andric const AttributeList &PAL = CI->getAttributes(); 2710b57cec5SDimitry Andric unsigned ArgNo = 0; 2725ffd83dbSDimitry Andric for (Value *Arg : I.args()) { 2730b57cec5SDimitry Andric // Skip ByVal arguments since they will be memcpy'd to the callee's 2740b57cec5SDimitry Andric // stack anyway. 275349cc55cSDimitry Andric if (PAL.hasParamAttr(ArgNo++, Attribute::ByVal)) 2760b57cec5SDimitry Andric continue; 2770b57cec5SDimitry Andric Value *Obj = findValue(Arg, /*OffsetOk=*/true); 27881ad6265SDimitry Andric Check(!isa<AllocaInst>(Obj), 2790b57cec5SDimitry Andric "Undefined behavior: Call with \"tail\" keyword references " 2800b57cec5SDimitry Andric "alloca", 2810b57cec5SDimitry Andric &I); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) 2870b57cec5SDimitry Andric switch (II->getIntrinsicID()) { 288e8d8bef9SDimitry Andric default: 289e8d8bef9SDimitry Andric break; 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric // TODO: Check more intrinsics 2920b57cec5SDimitry Andric 293*0fca6ea1SDimitry Andric case Intrinsic::memcpy: 294*0fca6ea1SDimitry Andric case Intrinsic::memcpy_inline: { 2950b57cec5SDimitry Andric MemCpyInst *MCI = cast<MemCpyInst>(&I); 296e8d8bef9SDimitry Andric visitMemoryReference(I, MemoryLocation::getForDest(MCI), 2975ffd83dbSDimitry Andric MCI->getDestAlign(), nullptr, MemRef::Write); 298e8d8bef9SDimitry Andric visitMemoryReference(I, MemoryLocation::getForSource(MCI), 2995ffd83dbSDimitry Andric MCI->getSourceAlign(), nullptr, MemRef::Read); 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric // Check that the memcpy arguments don't overlap. The AliasAnalysis API 3020b57cec5SDimitry Andric // isn't expressive enough for what we really want to do. Known partial 3030b57cec5SDimitry Andric // overlap is not distinguished from the case where nothing is known. 304e8d8bef9SDimitry Andric auto Size = LocationSize::afterPointer(); 3050b57cec5SDimitry Andric if (const ConstantInt *Len = 3060b57cec5SDimitry Andric dyn_cast<ConstantInt>(findValue(MCI->getLength(), 3070b57cec5SDimitry Andric /*OffsetOk=*/false))) 3080b57cec5SDimitry Andric if (Len->getValue().isIntN(32)) 3090b57cec5SDimitry Andric Size = LocationSize::precise(Len->getValue().getZExtValue()); 31081ad6265SDimitry Andric Check(AA->alias(MCI->getSource(), Size, MCI->getDest(), Size) != 311fe6060f1SDimitry Andric AliasResult::MustAlias, 3120b57cec5SDimitry Andric "Undefined behavior: memcpy source and destination overlap", &I); 3130b57cec5SDimitry Andric break; 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric case Intrinsic::memmove: { 3160b57cec5SDimitry Andric MemMoveInst *MMI = cast<MemMoveInst>(&I); 317e8d8bef9SDimitry Andric visitMemoryReference(I, MemoryLocation::getForDest(MMI), 3185ffd83dbSDimitry Andric MMI->getDestAlign(), nullptr, MemRef::Write); 319e8d8bef9SDimitry Andric visitMemoryReference(I, MemoryLocation::getForSource(MMI), 3205ffd83dbSDimitry Andric MMI->getSourceAlign(), nullptr, MemRef::Read); 3210b57cec5SDimitry Andric break; 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric case Intrinsic::memset: { 3240b57cec5SDimitry Andric MemSetInst *MSI = cast<MemSetInst>(&I); 325e8d8bef9SDimitry Andric visitMemoryReference(I, MemoryLocation::getForDest(MSI), 3265ffd83dbSDimitry Andric MSI->getDestAlign(), nullptr, MemRef::Write); 3270b57cec5SDimitry Andric break; 3280b57cec5SDimitry Andric } 32981ad6265SDimitry Andric case Intrinsic::memset_inline: { 33081ad6265SDimitry Andric MemSetInlineInst *MSII = cast<MemSetInlineInst>(&I); 33181ad6265SDimitry Andric visitMemoryReference(I, MemoryLocation::getForDest(MSII), 33281ad6265SDimitry Andric MSII->getDestAlign(), nullptr, MemRef::Write); 33381ad6265SDimitry Andric break; 33481ad6265SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric case Intrinsic::vastart: 337*0fca6ea1SDimitry Andric // vastart in non-varargs function is rejected by the verifier 338bdd1243dSDimitry Andric visitMemoryReference(I, MemoryLocation::getForArgument(&I, 0, TLI), 339bdd1243dSDimitry Andric std::nullopt, nullptr, MemRef::Read | MemRef::Write); 3400b57cec5SDimitry Andric break; 3410b57cec5SDimitry Andric case Intrinsic::vacopy: 342bdd1243dSDimitry Andric visitMemoryReference(I, MemoryLocation::getForArgument(&I, 0, TLI), 343bdd1243dSDimitry Andric std::nullopt, nullptr, MemRef::Write); 344bdd1243dSDimitry Andric visitMemoryReference(I, MemoryLocation::getForArgument(&I, 1, TLI), 345bdd1243dSDimitry Andric std::nullopt, nullptr, MemRef::Read); 3460b57cec5SDimitry Andric break; 3470b57cec5SDimitry Andric case Intrinsic::vaend: 348bdd1243dSDimitry Andric visitMemoryReference(I, MemoryLocation::getForArgument(&I, 0, TLI), 349bdd1243dSDimitry Andric std::nullopt, nullptr, MemRef::Read | MemRef::Write); 3500b57cec5SDimitry Andric break; 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric case Intrinsic::stackrestore: 3530b57cec5SDimitry Andric // Stackrestore doesn't read or write memory, but it sets the 3540b57cec5SDimitry Andric // stack pointer, which the compiler may read from or write to 3550b57cec5SDimitry Andric // at any time, so check it for both readability and writeability. 356bdd1243dSDimitry Andric visitMemoryReference(I, MemoryLocation::getForArgument(&I, 0, TLI), 357bdd1243dSDimitry Andric std::nullopt, nullptr, MemRef::Read | MemRef::Write); 358e8d8bef9SDimitry Andric break; 359e8d8bef9SDimitry Andric case Intrinsic::get_active_lane_mask: 360e8d8bef9SDimitry Andric if (auto *TripCount = dyn_cast<ConstantInt>(I.getArgOperand(1))) 36181ad6265SDimitry Andric Check(!TripCount->isZero(), 36281ad6265SDimitry Andric "get_active_lane_mask: operand #2 " 36381ad6265SDimitry Andric "must be greater than 0", 36481ad6265SDimitry Andric &I); 3650b57cec5SDimitry Andric break; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric void Lint::visitReturnInst(ReturnInst &I) { 3700b57cec5SDimitry Andric Function *F = I.getParent()->getParent(); 37181ad6265SDimitry Andric Check(!F->doesNotReturn(), 3720b57cec5SDimitry Andric "Unusual: Return statement in function with noreturn attribute", &I); 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric if (Value *V = I.getReturnValue()) { 3750b57cec5SDimitry Andric Value *Obj = findValue(V, /*OffsetOk=*/true); 37681ad6265SDimitry Andric Check(!isa<AllocaInst>(Obj), "Unusual: Returning alloca value", &I); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric // TODO: Check that the reference is in bounds. 3810b57cec5SDimitry Andric // TODO: Check readnone/readonly function attributes. 382e8d8bef9SDimitry Andric void Lint::visitMemoryReference(Instruction &I, const MemoryLocation &Loc, 3835ffd83dbSDimitry Andric MaybeAlign Align, Type *Ty, unsigned Flags) { 3840b57cec5SDimitry Andric // If no memory is being referenced, it doesn't matter if the pointer 3850b57cec5SDimitry Andric // is valid. 386e8d8bef9SDimitry Andric if (Loc.Size.isZero()) 3870b57cec5SDimitry Andric return; 3880b57cec5SDimitry Andric 389e8d8bef9SDimitry Andric Value *Ptr = const_cast<Value *>(Loc.Ptr); 3900b57cec5SDimitry Andric Value *UnderlyingObject = findValue(Ptr, /*OffsetOk=*/true); 39181ad6265SDimitry Andric Check(!isa<ConstantPointerNull>(UnderlyingObject), 3920b57cec5SDimitry Andric "Undefined behavior: Null pointer dereference", &I); 39381ad6265SDimitry Andric Check(!isa<UndefValue>(UnderlyingObject), 3940b57cec5SDimitry Andric "Undefined behavior: Undef pointer dereference", &I); 39581ad6265SDimitry Andric Check(!isa<ConstantInt>(UnderlyingObject) || 3960b57cec5SDimitry Andric !cast<ConstantInt>(UnderlyingObject)->isMinusOne(), 3970b57cec5SDimitry Andric "Unusual: All-ones pointer dereference", &I); 39881ad6265SDimitry Andric Check(!isa<ConstantInt>(UnderlyingObject) || 3990b57cec5SDimitry Andric !cast<ConstantInt>(UnderlyingObject)->isOne(), 4000b57cec5SDimitry Andric "Unusual: Address one pointer dereference", &I); 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric if (Flags & MemRef::Write) { 4030b57cec5SDimitry Andric if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(UnderlyingObject)) 40481ad6265SDimitry Andric Check(!GV->isConstant(), "Undefined behavior: Write to read-only memory", 4050b57cec5SDimitry Andric &I); 40681ad6265SDimitry Andric Check(!isa<Function>(UnderlyingObject) && 4070b57cec5SDimitry Andric !isa<BlockAddress>(UnderlyingObject), 4080b57cec5SDimitry Andric "Undefined behavior: Write to text section", &I); 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric if (Flags & MemRef::Read) { 41181ad6265SDimitry Andric Check(!isa<Function>(UnderlyingObject), "Unusual: Load from function body", 4120b57cec5SDimitry Andric &I); 41381ad6265SDimitry Andric Check(!isa<BlockAddress>(UnderlyingObject), 4140b57cec5SDimitry Andric "Undefined behavior: Load from block address", &I); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric if (Flags & MemRef::Callee) { 41781ad6265SDimitry Andric Check(!isa<BlockAddress>(UnderlyingObject), 4180b57cec5SDimitry Andric "Undefined behavior: Call to block address", &I); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric if (Flags & MemRef::Branchee) { 42181ad6265SDimitry Andric Check(!isa<Constant>(UnderlyingObject) || 4220b57cec5SDimitry Andric isa<BlockAddress>(UnderlyingObject), 4230b57cec5SDimitry Andric "Undefined behavior: Branch to non-blockaddress", &I); 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric // Check for buffer overflows and misalignment. 4270b57cec5SDimitry Andric // Only handles memory references that read/write something simple like an 4280b57cec5SDimitry Andric // alloca instruction or a global variable. 4290b57cec5SDimitry Andric int64_t Offset = 0; 4300b57cec5SDimitry Andric if (Value *Base = GetPointerBaseWithConstantOffset(Ptr, Offset, *DL)) { 4310b57cec5SDimitry Andric // OK, so the access is to a constant offset from Ptr. Check that Ptr is 4320b57cec5SDimitry Andric // something we can handle and if so extract the size of this base object 4330b57cec5SDimitry Andric // along with its alignment. 4340b57cec5SDimitry Andric uint64_t BaseSize = MemoryLocation::UnknownSize; 4355ffd83dbSDimitry Andric MaybeAlign BaseAlign; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric if (AllocaInst *AI = dyn_cast<AllocaInst>(Base)) { 4380b57cec5SDimitry Andric Type *ATy = AI->getAllocatedType(); 4390b57cec5SDimitry Andric if (!AI->isArrayAllocation() && ATy->isSized()) 4400b57cec5SDimitry Andric BaseSize = DL->getTypeAllocSize(ATy); 4415ffd83dbSDimitry Andric BaseAlign = AI->getAlign(); 4420b57cec5SDimitry Andric } else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) { 4430b57cec5SDimitry Andric // If the global may be defined differently in another compilation unit 4440b57cec5SDimitry Andric // then don't warn about funky memory accesses. 4450b57cec5SDimitry Andric if (GV->hasDefinitiveInitializer()) { 4460b57cec5SDimitry Andric Type *GTy = GV->getValueType(); 4470b57cec5SDimitry Andric if (GTy->isSized()) 4480b57cec5SDimitry Andric BaseSize = DL->getTypeAllocSize(GTy); 4495ffd83dbSDimitry Andric BaseAlign = GV->getAlign(); 4505ffd83dbSDimitry Andric if (!BaseAlign && GTy->isSized()) 4515ffd83dbSDimitry Andric BaseAlign = DL->getABITypeAlign(GTy); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric // Accesses from before the start or after the end of the object are not 4560b57cec5SDimitry Andric // defined. 45781ad6265SDimitry Andric Check(!Loc.Size.hasValue() || BaseSize == MemoryLocation::UnknownSize || 458e8d8bef9SDimitry Andric (Offset >= 0 && Offset + Loc.Size.getValue() <= BaseSize), 4590b57cec5SDimitry Andric "Undefined behavior: Buffer overflow", &I); 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric // Accesses that say that the memory is more aligned than it is are not 4620b57cec5SDimitry Andric // defined. 4635ffd83dbSDimitry Andric if (!Align && Ty && Ty->isSized()) 4645ffd83dbSDimitry Andric Align = DL->getABITypeAlign(Ty); 4655ffd83dbSDimitry Andric if (BaseAlign && Align) 46681ad6265SDimitry Andric Check(*Align <= commonAlignment(*BaseAlign, Offset), 4670b57cec5SDimitry Andric "Undefined behavior: Memory reference address is misaligned", &I); 4680b57cec5SDimitry Andric } 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric void Lint::visitLoadInst(LoadInst &I) { 472e8d8bef9SDimitry Andric visitMemoryReference(I, MemoryLocation::get(&I), I.getAlign(), I.getType(), 473e8d8bef9SDimitry Andric MemRef::Read); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric void Lint::visitStoreInst(StoreInst &I) { 477e8d8bef9SDimitry Andric visitMemoryReference(I, MemoryLocation::get(&I), I.getAlign(), 478e8d8bef9SDimitry Andric I.getOperand(0)->getType(), MemRef::Write); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric void Lint::visitXor(BinaryOperator &I) { 48281ad6265SDimitry Andric Check(!isa<UndefValue>(I.getOperand(0)) || !isa<UndefValue>(I.getOperand(1)), 4830b57cec5SDimitry Andric "Undefined result: xor(undef, undef)", &I); 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric void Lint::visitSub(BinaryOperator &I) { 48781ad6265SDimitry Andric Check(!isa<UndefValue>(I.getOperand(0)) || !isa<UndefValue>(I.getOperand(1)), 4880b57cec5SDimitry Andric "Undefined result: sub(undef, undef)", &I); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric void Lint::visitLShr(BinaryOperator &I) { 4920b57cec5SDimitry Andric if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getOperand(1), 4930b57cec5SDimitry Andric /*OffsetOk=*/false))) 49481ad6265SDimitry Andric Check(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()), 4950b57cec5SDimitry Andric "Undefined result: Shift count out of range", &I); 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric void Lint::visitAShr(BinaryOperator &I) { 4990b57cec5SDimitry Andric if (ConstantInt *CI = 5000b57cec5SDimitry Andric dyn_cast<ConstantInt>(findValue(I.getOperand(1), /*OffsetOk=*/false))) 50181ad6265SDimitry Andric Check(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()), 5020b57cec5SDimitry Andric "Undefined result: Shift count out of range", &I); 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric void Lint::visitShl(BinaryOperator &I) { 5060b57cec5SDimitry Andric if (ConstantInt *CI = 5070b57cec5SDimitry Andric dyn_cast<ConstantInt>(findValue(I.getOperand(1), /*OffsetOk=*/false))) 50881ad6265SDimitry Andric Check(CI->getValue().ult(cast<IntegerType>(I.getType())->getBitWidth()), 5090b57cec5SDimitry Andric "Undefined result: Shift count out of range", &I); 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, 5130b57cec5SDimitry Andric AssumptionCache *AC) { 5140b57cec5SDimitry Andric // Assume undef could be zero. 5150b57cec5SDimitry Andric if (isa<UndefValue>(V)) 5160b57cec5SDimitry Andric return true; 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric VectorType *VecTy = dyn_cast<VectorType>(V->getType()); 5190b57cec5SDimitry Andric if (!VecTy) { 520e8d8bef9SDimitry Andric KnownBits Known = 521e8d8bef9SDimitry Andric computeKnownBits(V, DL, 0, AC, dyn_cast<Instruction>(V), DT); 5220b57cec5SDimitry Andric return Known.isZero(); 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric // Per-component check doesn't work with zeroinitializer 5260b57cec5SDimitry Andric Constant *C = dyn_cast<Constant>(V); 5270b57cec5SDimitry Andric if (!C) 5280b57cec5SDimitry Andric return false; 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric if (C->isZeroValue()) 5310b57cec5SDimitry Andric return true; 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric // For a vector, KnownZero will only be true if all values are zero, so check 5340b57cec5SDimitry Andric // this per component 535e8d8bef9SDimitry Andric for (unsigned I = 0, N = cast<FixedVectorType>(VecTy)->getNumElements(); 536e8d8bef9SDimitry Andric I != N; ++I) { 5370b57cec5SDimitry Andric Constant *Elem = C->getAggregateElement(I); 5380b57cec5SDimitry Andric if (isa<UndefValue>(Elem)) 5390b57cec5SDimitry Andric return true; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric KnownBits Known = computeKnownBits(Elem, DL); 5420b57cec5SDimitry Andric if (Known.isZero()) 5430b57cec5SDimitry Andric return true; 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric return false; 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric void Lint::visitSDiv(BinaryOperator &I) { 550*0fca6ea1SDimitry Andric Check(!isZero(I.getOperand(1), I.getDataLayout(), DT, AC), 5510b57cec5SDimitry Andric "Undefined behavior: Division by zero", &I); 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric void Lint::visitUDiv(BinaryOperator &I) { 555*0fca6ea1SDimitry Andric Check(!isZero(I.getOperand(1), I.getDataLayout(), DT, AC), 5560b57cec5SDimitry Andric "Undefined behavior: Division by zero", &I); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric void Lint::visitSRem(BinaryOperator &I) { 560*0fca6ea1SDimitry Andric Check(!isZero(I.getOperand(1), I.getDataLayout(), DT, AC), 5610b57cec5SDimitry Andric "Undefined behavior: Division by zero", &I); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric void Lint::visitURem(BinaryOperator &I) { 565*0fca6ea1SDimitry Andric Check(!isZero(I.getOperand(1), I.getDataLayout(), DT, AC), 5660b57cec5SDimitry Andric "Undefined behavior: Division by zero", &I); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric void Lint::visitAllocaInst(AllocaInst &I) { 5700b57cec5SDimitry Andric if (isa<ConstantInt>(I.getArraySize())) 5710b57cec5SDimitry Andric // This isn't undefined behavior, it's just an obvious pessimization. 57281ad6265SDimitry Andric Check(&I.getParent()->getParent()->getEntryBlock() == I.getParent(), 5730b57cec5SDimitry Andric "Pessimization: Static alloca outside of entry block", &I); 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric // TODO: Check for an unusual size (MSB set?) 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric void Lint::visitVAArgInst(VAArgInst &I) { 579bdd1243dSDimitry Andric visitMemoryReference(I, MemoryLocation::get(&I), std::nullopt, nullptr, 580e8d8bef9SDimitry Andric MemRef::Read | MemRef::Write); 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric void Lint::visitIndirectBrInst(IndirectBrInst &I) { 584bdd1243dSDimitry Andric visitMemoryReference(I, MemoryLocation::getAfter(I.getAddress()), 585bdd1243dSDimitry Andric std::nullopt, nullptr, MemRef::Branchee); 5860b57cec5SDimitry Andric 58781ad6265SDimitry Andric Check(I.getNumDestinations() != 0, 5880b57cec5SDimitry Andric "Undefined behavior: indirectbr with no destinations", &I); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric void Lint::visitExtractElementInst(ExtractElementInst &I) { 5920b57cec5SDimitry Andric if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getIndexOperand(), 5930b57cec5SDimitry Andric /*OffsetOk=*/false))) 59481ad6265SDimitry Andric Check( 595e8d8bef9SDimitry Andric CI->getValue().ult( 596e8d8bef9SDimitry Andric cast<FixedVectorType>(I.getVectorOperandType())->getNumElements()), 5970b57cec5SDimitry Andric "Undefined result: extractelement index out of range", &I); 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric void Lint::visitInsertElementInst(InsertElementInst &I) { 6010b57cec5SDimitry Andric if (ConstantInt *CI = dyn_cast<ConstantInt>(findValue(I.getOperand(2), 6020b57cec5SDimitry Andric /*OffsetOk=*/false))) 60381ad6265SDimitry Andric Check(CI->getValue().ult( 604e8d8bef9SDimitry Andric cast<FixedVectorType>(I.getType())->getNumElements()), 6050b57cec5SDimitry Andric "Undefined result: insertelement index out of range", &I); 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric void Lint::visitUnreachableInst(UnreachableInst &I) { 6090b57cec5SDimitry Andric // This isn't undefined behavior, it's merely suspicious. 61081ad6265SDimitry Andric Check(&I == &I.getParent()->front() || 6110b57cec5SDimitry Andric std::prev(I.getIterator())->mayHaveSideEffects(), 6120b57cec5SDimitry Andric "Unusual: unreachable immediately preceded by instruction without " 6130b57cec5SDimitry Andric "side effects", 6140b57cec5SDimitry Andric &I); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric /// findValue - Look through bitcasts and simple memory reference patterns 6180b57cec5SDimitry Andric /// to identify an equivalent, but more informative, value. If OffsetOk 6190b57cec5SDimitry Andric /// is true, look through getelementptrs with non-zero offsets too. 6200b57cec5SDimitry Andric /// 6210b57cec5SDimitry Andric /// Most analysis passes don't require this logic, because instcombine 6220b57cec5SDimitry Andric /// will simplify most of these kinds of things away. But it's a goal of 6230b57cec5SDimitry Andric /// this Lint pass to be useful even on non-optimized IR. 6240b57cec5SDimitry Andric Value *Lint::findValue(Value *V, bool OffsetOk) const { 6250b57cec5SDimitry Andric SmallPtrSet<Value *, 4> Visited; 6260b57cec5SDimitry Andric return findValueImpl(V, OffsetOk, Visited); 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric /// findValueImpl - Implementation helper for findValue. 6300b57cec5SDimitry Andric Value *Lint::findValueImpl(Value *V, bool OffsetOk, 6310b57cec5SDimitry Andric SmallPtrSetImpl<Value *> &Visited) const { 6320b57cec5SDimitry Andric // Detect self-referential values. 6330b57cec5SDimitry Andric if (!Visited.insert(V).second) 634*0fca6ea1SDimitry Andric return PoisonValue::get(V->getType()); 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric // TODO: Look through sext or zext cast, when the result is known to 6370b57cec5SDimitry Andric // be interpreted as signed or unsigned, respectively. 6380b57cec5SDimitry Andric // TODO: Look through eliminable cast pairs. 6390b57cec5SDimitry Andric // TODO: Look through calls with unique return values. 6400b57cec5SDimitry Andric // TODO: Look through vector insert/extract/shuffle. 641e8d8bef9SDimitry Andric V = OffsetOk ? getUnderlyingObject(V) : V->stripPointerCasts(); 6420b57cec5SDimitry Andric if (LoadInst *L = dyn_cast<LoadInst>(V)) { 6430b57cec5SDimitry Andric BasicBlock::iterator BBI = L->getIterator(); 6440b57cec5SDimitry Andric BasicBlock *BB = L->getParent(); 6450b57cec5SDimitry Andric SmallPtrSet<BasicBlock *, 4> VisitedBlocks; 646b3edf446SDimitry Andric BatchAAResults BatchAA(*AA); 6470b57cec5SDimitry Andric for (;;) { 6480b57cec5SDimitry Andric if (!VisitedBlocks.insert(BB).second) 6490b57cec5SDimitry Andric break; 6500b57cec5SDimitry Andric if (Value *U = 651b3edf446SDimitry Andric FindAvailableLoadedValue(L, BB, BBI, DefMaxInstsToScan, &BatchAA)) 6520b57cec5SDimitry Andric return findValueImpl(U, OffsetOk, Visited); 653e8d8bef9SDimitry Andric if (BBI != BB->begin()) 654e8d8bef9SDimitry Andric break; 6550b57cec5SDimitry Andric BB = BB->getUniquePredecessor(); 656e8d8bef9SDimitry Andric if (!BB) 657e8d8bef9SDimitry Andric break; 6580b57cec5SDimitry Andric BBI = BB->end(); 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric } else if (PHINode *PN = dyn_cast<PHINode>(V)) { 6610b57cec5SDimitry Andric if (Value *W = PN->hasConstantValue()) 6620b57cec5SDimitry Andric return findValueImpl(W, OffsetOk, Visited); 6630b57cec5SDimitry Andric } else if (CastInst *CI = dyn_cast<CastInst>(V)) { 6640b57cec5SDimitry Andric if (CI->isNoopCast(*DL)) 6650b57cec5SDimitry Andric return findValueImpl(CI->getOperand(0), OffsetOk, Visited); 6660b57cec5SDimitry Andric } else if (ExtractValueInst *Ex = dyn_cast<ExtractValueInst>(V)) { 667e8d8bef9SDimitry Andric if (Value *W = 668e8d8bef9SDimitry Andric FindInsertedValue(Ex->getAggregateOperand(), Ex->getIndices())) 6690b57cec5SDimitry Andric if (W != V) 6700b57cec5SDimitry Andric return findValueImpl(W, OffsetOk, Visited); 6710b57cec5SDimitry Andric } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { 6720b57cec5SDimitry Andric // Same as above, but for ConstantExpr instead of Instruction. 6730b57cec5SDimitry Andric if (Instruction::isCast(CE->getOpcode())) { 6740b57cec5SDimitry Andric if (CastInst::isNoopCast(Instruction::CastOps(CE->getOpcode()), 6750b57cec5SDimitry Andric CE->getOperand(0)->getType(), CE->getType(), 6760b57cec5SDimitry Andric *DL)) 6770b57cec5SDimitry Andric return findValueImpl(CE->getOperand(0), OffsetOk, Visited); 6780b57cec5SDimitry Andric } 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric // As a last resort, try SimplifyInstruction or constant folding. 6820b57cec5SDimitry Andric if (Instruction *Inst = dyn_cast<Instruction>(V)) { 68381ad6265SDimitry Andric if (Value *W = simplifyInstruction(Inst, {*DL, TLI, DT, AC})) 6840b57cec5SDimitry Andric return findValueImpl(W, OffsetOk, Visited); 6850b57cec5SDimitry Andric } else if (auto *C = dyn_cast<Constant>(V)) { 6865ffd83dbSDimitry Andric Value *W = ConstantFoldConstant(C, *DL, TLI); 6875ffd83dbSDimitry Andric if (W != V) 6880b57cec5SDimitry Andric return findValueImpl(W, OffsetOk, Visited); 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric return V; 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric 694e8d8bef9SDimitry Andric PreservedAnalyses LintPass::run(Function &F, FunctionAnalysisManager &AM) { 695e8d8bef9SDimitry Andric auto *Mod = F.getParent(); 696*0fca6ea1SDimitry Andric auto *DL = &F.getDataLayout(); 697e8d8bef9SDimitry Andric auto *AA = &AM.getResult<AAManager>(F); 698e8d8bef9SDimitry Andric auto *AC = &AM.getResult<AssumptionAnalysis>(F); 699e8d8bef9SDimitry Andric auto *DT = &AM.getResult<DominatorTreeAnalysis>(F); 700e8d8bef9SDimitry Andric auto *TLI = &AM.getResult<TargetLibraryAnalysis>(F); 701e8d8bef9SDimitry Andric Lint L(Mod, DL, AA, AC, DT, TLI); 702e8d8bef9SDimitry Andric L.visit(F); 703e8d8bef9SDimitry Andric dbgs() << L.MessagesStr.str(); 704*0fca6ea1SDimitry Andric if (LintAbortOnError && !L.MessagesStr.str().empty()) 705*0fca6ea1SDimitry Andric report_fatal_error(Twine("Linter found errors, aborting. (enabled by --") + 706*0fca6ea1SDimitry Andric LintAbortOnErrorArgName + ")", 707*0fca6ea1SDimitry Andric false); 708e8d8bef9SDimitry Andric return PreservedAnalyses::all(); 709e8d8bef9SDimitry Andric } 710e8d8bef9SDimitry Andric 7110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7120b57cec5SDimitry Andric // Implement the public interfaces to this file... 7130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric /// lintFunction - Check a function for errors, printing messages on stderr. 7160b57cec5SDimitry Andric /// 7170b57cec5SDimitry Andric void llvm::lintFunction(const Function &f) { 7180b57cec5SDimitry Andric Function &F = const_cast<Function &>(f); 7190b57cec5SDimitry Andric assert(!F.isDeclaration() && "Cannot lint external functions"); 7200b57cec5SDimitry Andric 72106c3fb27SDimitry Andric FunctionAnalysisManager FAM; 72206c3fb27SDimitry Andric FAM.registerPass([&] { return TargetLibraryAnalysis(); }); 72306c3fb27SDimitry Andric FAM.registerPass([&] { return DominatorTreeAnalysis(); }); 72406c3fb27SDimitry Andric FAM.registerPass([&] { return AssumptionAnalysis(); }); 72506c3fb27SDimitry Andric FAM.registerPass([&] { 72606c3fb27SDimitry Andric AAManager AA; 72706c3fb27SDimitry Andric AA.registerFunctionAnalysis<BasicAA>(); 72806c3fb27SDimitry Andric AA.registerFunctionAnalysis<ScopedNoAliasAA>(); 72906c3fb27SDimitry Andric AA.registerFunctionAnalysis<TypeBasedAA>(); 73006c3fb27SDimitry Andric return AA; 73106c3fb27SDimitry Andric }); 73206c3fb27SDimitry Andric LintPass().run(F, FAM); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric /// lintModule - Check a module for errors, printing messages on stderr. 7360b57cec5SDimitry Andric /// 7370b57cec5SDimitry Andric void llvm::lintModule(const Module &M) { 73806c3fb27SDimitry Andric for (const Function &F : M) { 73906c3fb27SDimitry Andric if (!F.isDeclaration()) 74006c3fb27SDimitry Andric lintFunction(F); 74106c3fb27SDimitry Andric } 7420b57cec5SDimitry Andric } 743