82static const unsigned Read = 1;
83static const unsigned Write = 2;
84static const unsigned Callee = 4;
85static const unsigned Branchee = 8;
118 Value *findValue(
Value *V,
bool OffsetOk)
const;
130 std::string Messages;
135 :
Mod(
Mod),
DL(
DL), AA(AA), AC(AC), DT(DT), TLI(TLI),
136 MessagesStr(Messages) {}
139 for (
const Value *V : Vs) {
142 if (isa<Instruction>(V)) {
143 MessagesStr << *V <<
'\n';
145 V->printAsOperand(MessagesStr,
true,
Mod);
155 void CheckFailed(
const Twine &Message) { MessagesStr << Message <<
'\n'; }
161 template <
typename T1,
typename... Ts>
162 void CheckFailed(
const Twine &Message,
const T1 &V1,
const Ts &... Vs) {
163 CheckFailed(Message);
164 WriteValues({V1, Vs...});
170#define Check(C, ...) \
173 CheckFailed(__VA_ARGS__); \
181 Check(
F.hasName() ||
F.hasLocalLinkage(),
182 "Unusual: Unnamed function with non-local linkage", &
F);
191 nullptr, MemRef::Callee);
195 Check(
I.getCallingConv() ==
F->getCallingConv(),
196 "Undefined behavior: Caller and callee calling convention differ",
200 unsigned NumActualArgs =
I.arg_size();
202 Check(FT->isVarArg() ? FT->getNumParams() <= NumActualArgs
203 : FT->getNumParams() == NumActualArgs,
204 "Undefined behavior: Call argument count mismatches callee "
208 Check(FT->getReturnType() ==
I.getType(),
209 "Undefined behavior: Call return type mismatches "
210 "callee return type",
216 auto AI =
I.arg_begin(), AE =
I.arg_end();
217 for (; AI != AE; ++AI) {
222 "Undefined behavior: Call argument type mismatches "
223 "callee parameter type",
232 for (
auto *BI =
I.arg_begin(); BI != AE; ++BI, ++ArgNo) {
240 if (AI != BI && (*BI)->getType()->isPointerTy()) {
244 "Unusual: noalias argument aliases another argument", &
I);
254 visitMemoryReference(
I, Loc,
DL->getABITypeAlign(Ty), Ty,
255 MemRef::Read | MemRef::Write);
261 if (
const auto *CI = dyn_cast<CallInst>(&
I)) {
262 if (CI->isTailCall()) {
271 Check(!isa<AllocaInst>(Obj),
272 "Undefined behavior: Call with \"tail\" keyword references "
280 switch (II->getIntrinsicID()) {
286 case Intrinsic::memcpy: {
298 dyn_cast<ConstantInt>(findValue(MCI->
getLength(),
300 if (
Len->getValue().isIntN(32))
304 "Undefined behavior: memcpy source and destination overlap", &
I);
307 case Intrinsic::memcpy_inline: {
321 "Undefined behavior: memcpy source and destination overlap", &
I);
324 case Intrinsic::memmove: {
332 case Intrinsic::memset: {
338 case Intrinsic::memset_inline: {
345 case Intrinsic::vastart:
346 Check(
I.getParent()->getParent()->isVarArg(),
347 "Undefined behavior: va_start called in a non-varargs function",
351 std::nullopt,
nullptr, MemRef::Read | MemRef::Write);
353 case Intrinsic::vacopy:
355 std::nullopt,
nullptr, MemRef::Write);
357 std::nullopt,
nullptr, MemRef::Read);
359 case Intrinsic::vaend:
361 std::nullopt,
nullptr, MemRef::Read | MemRef::Write);
364 case Intrinsic::stackrestore:
369 std::nullopt,
nullptr, MemRef::Read | MemRef::Write);
371 case Intrinsic::get_active_lane_mask:
372 if (
auto *TripCount = dyn_cast<ConstantInt>(
I.getArgOperand(1)))
373 Check(!TripCount->isZero(),
374 "get_active_lane_mask: operand #2 "
375 "must be greater than 0",
383 Check(!
F->doesNotReturn(),
384 "Unusual: Return statement in function with noreturn attribute", &
I);
386 if (
Value *V =
I.getReturnValue()) {
387 Value *Obj = findValue(V,
true);
388 Check(!isa<AllocaInst>(Obj),
"Unusual: Returning alloca value", &
I);
404 "Undefined behavior: Null pointer dereference", &
I);
406 "Undefined behavior: Undef pointer dereference", &
I);
409 "Unusual: All-ones pointer dereference", &
I);
412 "Unusual: Address one pointer dereference", &
I);
414 if (Flags & MemRef::Write) {
416 Check(!GV->isConstant(),
"Undefined behavior: Write to read-only memory",
420 "Undefined behavior: Write to text section", &
I);
422 if (Flags & MemRef::Read) {
426 "Undefined behavior: Load from block address", &
I);
428 if (Flags & MemRef::Callee) {
430 "Undefined behavior: Call to block address", &
I);
432 if (Flags & MemRef::Branchee) {
435 "Undefined behavior: Branch to non-blockaddress", &
I);
450 Type *ATy = AI->getAllocatedType();
451 if (!AI->isArrayAllocation() && ATy->
isSized())
452 BaseSize =
DL->getTypeAllocSize(ATy);
453 BaseAlign = AI->getAlign();
457 if (GV->hasDefinitiveInitializer()) {
458 Type *GTy = GV->getValueType();
460 BaseSize =
DL->getTypeAllocSize(GTy);
461 BaseAlign = GV->getAlign();
462 if (!BaseAlign && GTy->
isSized())
463 BaseAlign =
DL->getABITypeAlign(GTy);
471 "Undefined behavior: Buffer overflow", &
I);
476 Align =
DL->getABITypeAlign(Ty);
477 if (BaseAlign &&
Align)
479 "Undefined behavior: Memory reference address is misaligned", &
I);
490 I.getOperand(0)->getType(), MemRef::Write);
494 Check(!isa<UndefValue>(
I.getOperand(0)) || !isa<UndefValue>(
I.getOperand(1)),
495 "Undefined result: xor(undef, undef)", &
I);
499 Check(!isa<UndefValue>(
I.getOperand(0)) || !isa<UndefValue>(
I.getOperand(1)),
500 "Undefined result: sub(undef, undef)", &
I);
504 if (
ConstantInt *CI = dyn_cast<ConstantInt>(findValue(
I.getOperand(1),
506 Check(CI->getValue().ult(cast<IntegerType>(
I.getType())->getBitWidth()),
507 "Undefined result: Shift count out of range", &
I);
512 dyn_cast<ConstantInt>(findValue(
I.getOperand(1),
false)))
513 Check(CI->getValue().ult(cast<IntegerType>(
I.getType())->getBitWidth()),
514 "Undefined result: Shift count out of range", &
I);
519 dyn_cast<ConstantInt>(findValue(
I.getOperand(1),
false)))
520 Check(CI->getValue().ult(cast<IntegerType>(
I.getType())->getBitWidth()),
521 "Undefined result: Shift count out of range", &
I);
527 if (isa<UndefValue>(V))
542 if (
C->isZeroValue())
547 for (
unsigned I = 0,
N = cast<FixedVectorType>(VecTy)->getNumElements();
550 if (isa<UndefValue>(Elem))
562 Check(!
isZero(
I.getOperand(1),
I.getModule()->getDataLayout(), DT, AC),
563 "Undefined behavior: Division by zero", &
I);
567 Check(!
isZero(
I.getOperand(1),
I.getModule()->getDataLayout(), DT, AC),
568 "Undefined behavior: Division by zero", &
I);
572 Check(!
isZero(
I.getOperand(1),
I.getModule()->getDataLayout(), DT, AC),
573 "Undefined behavior: Division by zero", &
I);
577 Check(!
isZero(
I.getOperand(1),
I.getModule()->getDataLayout(), DT, AC),
578 "Undefined behavior: Division by zero", &
I);
582 if (isa<ConstantInt>(
I.getArraySize()))
584 Check(&
I.getParent()->getParent()->getEntryBlock() ==
I.getParent(),
585 "Pessimization: Static alloca outside of entry block", &
I);
592 MemRef::Read | MemRef::Write);
597 std::nullopt,
nullptr, MemRef::Branchee);
599 Check(
I.getNumDestinations() != 0,
600 "Undefined behavior: indirectbr with no destinations", &
I);
604 if (
ConstantInt *CI = dyn_cast<ConstantInt>(findValue(
I.getIndexOperand(),
608 cast<FixedVectorType>(
I.getVectorOperandType())->getNumElements()),
609 "Undefined result: extractelement index out of range", &
I);
613 if (
ConstantInt *CI = dyn_cast<ConstantInt>(findValue(
I.getOperand(2),
615 Check(CI->getValue().ult(
616 cast<FixedVectorType>(
I.getType())->getNumElements()),
617 "Undefined result: insertelement index out of range", &
I);
622 Check(&
I == &
I.getParent()->front() ||
623 std::prev(
I.getIterator())->mayHaveSideEffects(),
624 "Unusual: unreachable immediately preceded by instruction without "
636Value *Lint::findValue(
Value *V,
bool OffsetOk)
const {
638 return findValueImpl(V, OffsetOk, Visited);
642Value *Lint::findValueImpl(
Value *V,
bool OffsetOk,
645 if (!Visited.
insert(V).second)
654 if (
LoadInst *L = dyn_cast<LoadInst>(V)) {
659 if (!VisitedBlocks.
insert(BB).second)
663 return findValueImpl(U, OffsetOk, Visited);
664 if (BBI != BB->
begin())
671 }
else if (
PHINode *PN = dyn_cast<PHINode>(V)) {
672 if (
Value *W = PN->hasConstantValue())
673 return findValueImpl(W, OffsetOk, Visited);
674 }
else if (
CastInst *CI = dyn_cast<CastInst>(V)) {
675 if (CI->isNoopCast(*
DL))
676 return findValueImpl(CI->getOperand(0), OffsetOk, Visited);
681 return findValueImpl(W, OffsetOk, Visited);
682 }
else if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
686 CE->getOperand(0)->getType(),
CE->getType(),
688 return findValueImpl(
CE->getOperand(0), OffsetOk, Visited);
693 if (
Instruction *Inst = dyn_cast<Instruction>(V)) {
695 return findValueImpl(W, OffsetOk, Visited);
696 }
else if (
auto *
C = dyn_cast<Constant>(V)) {
699 return findValueImpl(W, OffsetOk, Visited);
706 auto *
Mod =
F.getParent();
707 auto *
DL = &
F.getParent()->getDataLayout();
712 Lint L(
Mod,
DL, AA, AC, DT, TLI);
714 dbgs() << L.MessagesStr.str();
739char LintLegacyPass::ID = 0;
750 auto *
Mod =
F.getParent();
751 auto *
DL = &
F.getParent()->getDataLayout();
752 auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
753 auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
754 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
755 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
756 Lint L(
Mod,
DL, AA, AC, DT, TLI);
758 dbgs() << L.MessagesStr.str();
772 assert(!
F.isDeclaration() &&
"Cannot lint external functions");
775 auto *V =
new LintLegacyPass();
784 auto *V =
new LintLegacyPass();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Callee
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
This file implements a class to represent arbitrary precision integral constant values and operations...
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Statically lint checks LLVM IR
This file provides utility analysis objects describing memory locations.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
The main low level interface to the alias analysis implementation.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
The possible results of an alias query.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
an instruction to allocate memory on the stack
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
This class represents an incoming formal argument to a Function.
bool hasNoAliasAttr() const
Return true if this argument has the noalias attribute.
bool onlyReadsMemory() const
Return true if this argument has the readonly or readnone attribute.
Type * getParamStructRetType() const
If this is an sret argument, return its type.
bool hasStructRetAttr() const
Return true if this argument has the sret attribute.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Return true if the attribute exists for the given argument.
AttributeSet getAttributes(unsigned Index) const
The attributes for the specified index are returned.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
This is the base class for all instructions that perform data casts.
static bool isNoopCast(Instruction::CastOps Opcode, Type *SrcTy, Type *DstTy, const DataLayout &DL)
A no-op cast is one that can be effected without changing any bits.
A constant value that is initialized with an expression using other constant values.
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
Indirect Branch Instruction.
This instruction inserts a single (scalar) element into a VectorType value.
Base class for instruction visitors.
RetTy visitIndirectBrInst(IndirectBrInst &I)
RetTy visitExtractElementInst(ExtractElementInst &I)
RetTy visitCallBase(CallBase &I)
void visitFunction(Function &F)
RetTy visitUnreachableInst(UnreachableInst &I)
RetTy visitReturnInst(ReturnInst &I)
RetTy visitStoreInst(StoreInst &I)
RetTy visitInsertElementInst(InsertElementInst &I)
RetTy visitAllocaInst(AllocaInst &I)
RetTy visitLoadInst(LoadInst &I)
RetTy visitVAArgInst(VAArgInst &I)
A wrapper class for inspecting calls to intrinsic functions.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
An instruction for reading from memory.
static LocationSize precise(uint64_t Value)
uint64_t getValue() const
static constexpr LocationSize afterPointer()
Any location after the base pointer (but still within the underlying object).
This class wraps the llvm.memcpy.inline intrinsic.
ConstantInt * getLength() const
This class wraps the llvm.memcpy intrinsic.
Value * getLength() const
Value * getDest() const
This is just like getRawDest, but it strips off any cast instructions (including addrspacecast) that ...
MaybeAlign getDestAlign() const
This class wraps the llvm.memmove intrinsic.
This class wraps the llvm.memset.inline intrinsic.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
MaybeAlign getSourceAlign() const
Value * getSource() const
This is just like getRawSource, but it strips off any cast instructions that feed it,...
Representation for a specific memory location.
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
static MemoryLocation getForSource(const MemTransferInst *MTI)
Return a location representing the source of a memory transfer.
LocationSize Size
The maximum size of the location, in address-units, or UnknownSize if the size is not known.
static MemoryLocation getAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location after Ptr, while remaining within the underlying objec...
const Value * Ptr
The address of the start of the location.
static MemoryLocation getForDest(const MemIntrinsic *MI)
Return a location representing the destination of a memory set or transfer.
static MemoryLocation getForArgument(const CallBase *Call, unsigned ArgIdx, const TargetLibraryInfo *TLI)
Return a location representing a particular argument of a call.
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Return a value (possibly void), from a function.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
An instruction for storing to memory.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This function has undefined behavior.
This class represents the va_arg llvm instruction, which returns an argument of the specified type gi...
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
FunctionPassManager manages FunctionPasses.
bool run(Function &F)
run - Execute all of the passes scheduled for execution.
void add(Pass *P) override
Add a pass to the queue of passes to run.
PassManager manages ModulePassManagers.
void add(Pass *P) override
Add a pass to the queue of passes to run.
bool run(Module &M)
run - Execute all of the passes scheduled for execution.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ CE
Windows NT (Windows on ARM)
This is an optimization pass for GlobalISel generic memory operations.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments and pointer casts from the specified value,...
Value * FindAvailableLoadedValue(LoadInst *Load, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan=DefMaxInstsToScan, AAResults *AA=nullptr, bool *IsLoadCSE=nullptr, unsigned *NumScanedInst=nullptr)
Scan backwards to see if we have the value of the given load available locally within a small number ...
Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Fold the constant using the specified DataLayout.
Value * FindInsertedValue(Value *V, ArrayRef< unsigned > idx_range, Instruction *InsertBefore=nullptr)
Given an aggregate and an sequence of indices, see if the scalar value indexed is already around as a...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void lintModule(const Module &M)
Lint a module.
cl::opt< unsigned > DefMaxInstsToScan
The default number of maximum instructions to scan in the block, used by FindAvailableLoadedValue().
@ Mod
The access may modify the value stored in memory.
void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, OptimizationRemarkEmitter *ORE=nullptr, bool UseInstrInfo=true)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q, OptimizationRemarkEmitter *ORE=nullptr)
See if we can compute a simplified version of this instruction.
FunctionPass * createLintLegacyPassPass()
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
void initializeLintLegacyPassPass(PassRegistry &)
void lintFunction(const Function &F)
lintFunction - Check a function for errors, printing messages on stderr.
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool isZero() const
Returns true if value is all zero.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.