84 static const unsigned Read = 1;
85 static const unsigned Write = 2;
86 static const unsigned Callee = 4;
87 static const unsigned Branchee = 8;
97 uint64_t Size,
unsigned Align,
123 Value *findValue(
Value *V,
bool OffsetOk)
const;
135 std::string Messages;
143 bool runOnFunction(
Function &
F)
override;
155 for (
const Value *V : Vs) {
158 if (isa<Instruction>(V)) {
159 MessagesStr << *V <<
'\n';
161 V->printAsOperand(MessagesStr,
true, Mod);
171 void CheckFailed(
const Twine &Message) { MessagesStr << Message <<
'\n'; }
177 template <
typename T1,
typename... Ts>
178 void CheckFailed(
const Twine &Message,
const T1 &V1,
const Ts &...Vs) {
179 CheckFailed(Message);
180 WriteValues({V1, Vs...});
196 #define Assert(C, ...) \
197 do { if (!(C)) { CheckFailed(__VA_ARGS__); return; } } while (false)
205 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
206 AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
207 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
208 TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
210 dbgs() << MessagesStr.str();
219 "Unusual: Unnamed function with non-local linkage", &
F);
224 void Lint::visitCallSite(
CallSite CS) {
231 if (
Function *F = dyn_cast<Function>(findValue(Callee,
234 "Undefined behavior: Caller and callee calling convention differ",
238 unsigned NumActualArgs = CS.
arg_size();
240 Assert(FT->isVarArg() ? FT->getNumParams() <= NumActualArgs
241 : FT->getNumParams() == NumActualArgs,
242 "Undefined behavior: Call argument count mismatches callee "
247 "Undefined behavior: Call return type mismatches "
248 "callee return type",
255 for (; AI != AE; ++AI) {
260 "Undefined behavior: Call argument type mismatches "
261 "callee parameter type",
269 if (AI != BI && (*BI)->getType()->isPointerTy()) {
272 "Unusual: noalias argument aliases another argument", &I);
278 cast<PointerType>(Formal->
getType())->getElementType();
279 visitMemoryReference(I, Actual,
DL->getTypeStoreSize(Ty),
280 DL->getABITypeAlignment(Ty), Ty,
281 MemRef::Read | MemRef::Write);
290 Value *Obj = findValue(*AI,
true);
291 Assert(!isa<AllocaInst>(Obj),
292 "Undefined behavior: Call with \"tail\" keyword references "
299 switch (II->getIntrinsicID()) {
304 case Intrinsic::memcpy: {
317 dyn_cast<ConstantInt>(findValue(MCI->
getLength(),
319 if (Len->getValue().isIntN(32))
320 Size = Len->getValue().getZExtValue();
323 "Undefined behavior: memcpy source and destination overlap", &I);
326 case Intrinsic::memmove: {
335 case Intrinsic::memset: {
343 case Intrinsic::vastart:
345 "Undefined behavior: va_start called in a non-varargs function",
349 nullptr, MemRef::Read | MemRef::Write);
351 case Intrinsic::vacopy:
353 nullptr, MemRef::Write);
355 nullptr, MemRef::Read);
357 case Intrinsic::vaend:
359 nullptr, MemRef::Read | MemRef::Write);
362 case Intrinsic::stackrestore:
367 nullptr, MemRef::Read | MemRef::Write);
372 void Lint::visitCallInst(
CallInst &I) {
373 return visitCallSite(&I);
377 return visitCallSite(&I);
383 "Unusual: Return statement in function with noreturn attribute", &
I);
386 Value *Obj = findValue(V,
true);
387 Assert(!isa<AllocaInst>(Obj),
"Unusual: Returning alloca value", &I);
394 Value *
Ptr, uint64_t Size,
unsigned Align,
402 Assert(!isa<ConstantPointerNull>(UnderlyingObject),
403 "Undefined behavior: Null pointer dereference", &I);
404 Assert(!isa<UndefValue>(UnderlyingObject),
405 "Undefined behavior: Undef pointer dereference", &I);
406 Assert(!isa<ConstantInt>(UnderlyingObject) ||
407 !cast<ConstantInt>(UnderlyingObject)->isAllOnesValue(),
408 "Unusual: All-ones pointer dereference", &I);
409 Assert(!isa<ConstantInt>(UnderlyingObject) ||
410 !cast<ConstantInt>(UnderlyingObject)->isOne(),
411 "Unusual: Address one pointer dereference", &I);
413 if (Flags & MemRef::Write) {
414 if (
const GlobalVariable *GV = dyn_cast<GlobalVariable>(UnderlyingObject))
415 Assert(!GV->isConstant(),
"Undefined behavior: Write to read-only memory",
417 Assert(!isa<Function>(UnderlyingObject) &&
418 !isa<BlockAddress>(UnderlyingObject),
419 "Undefined behavior: Write to text section", &I);
421 if (Flags & MemRef::Read) {
422 Assert(!isa<Function>(UnderlyingObject),
"Unusual: Load from function body",
424 Assert(!isa<BlockAddress>(UnderlyingObject),
425 "Undefined behavior: Load from block address", &I);
427 if (Flags & MemRef::Callee) {
428 Assert(!isa<BlockAddress>(UnderlyingObject),
429 "Undefined behavior: Call to block address", &I);
431 if (Flags & MemRef::Branchee) {
432 Assert(!isa<Constant>(UnderlyingObject) ||
433 isa<BlockAddress>(UnderlyingObject),
434 "Undefined behavior: Branch to non-blockaddress", &I);
446 unsigned BaseAlign = 0;
448 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Base)) {
449 Type *ATy = AI->getAllocatedType();
450 if (!AI->isArrayAllocation() && ATy->
isSized())
451 BaseSize =
DL->getTypeAllocSize(ATy);
452 BaseAlign = AI->getAlignment();
453 if (BaseAlign == 0 && ATy->
isSized())
454 BaseAlign =
DL->getABITypeAlignment(ATy);
458 if (GV->hasDefinitiveInitializer()) {
459 Type *GTy = GV->getValueType();
461 BaseSize =
DL->getTypeAllocSize(GTy);
462 BaseAlign = GV->getAlignment();
463 if (BaseAlign == 0 && GTy->
isSized())
464 BaseAlign =
DL->getABITypeAlignment(GTy);
472 (Offset >= 0 && Offset + Size <= BaseSize),
473 "Undefined behavior: Buffer overflow", &I);
477 if (Align == 0 && Ty && Ty->
isSized())
478 Align =
DL->getABITypeAlignment(Ty);
480 "Undefined behavior: Memory reference address is misaligned", &I);
484 void Lint::visitLoadInst(
LoadInst &I) {
490 void Lint::visitStoreInst(
StoreInst &I) {
499 "Undefined result: xor(undef, undef)", &I);
504 "Undefined result: sub(undef, undef)", &I);
511 "Undefined result: Shift count out of range", &I);
516 dyn_cast<ConstantInt>(findValue(I.
getOperand(1),
false)))
518 "Undefined result: Shift count out of range", &I);
523 dyn_cast<ConstantInt>(findValue(I.
getOperand(1),
false)))
525 "Undefined result: Shift count out of range", &I);
531 if (isa<UndefValue>(V))
537 APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
539 dyn_cast<Instruction>(V), DT);
540 return KnownZero.isAllOnesValue();
556 if (isa<UndefValue>(Elem))
559 APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
561 if (KnownZero.isAllOnesValue())
570 "Undefined behavior: Division by zero", &I);
575 "Undefined behavior: Division by zero", &I);
580 "Undefined behavior: Division by zero", &I);
585 "Undefined behavior: Division by zero", &I);
592 "Pessimization: Static alloca outside of entry block", &
I);
597 void Lint::visitVAArgInst(
VAArgInst &I) {
599 nullptr, MemRef::Read | MemRef::Write);
604 nullptr, MemRef::Branchee);
607 "Undefined behavior: indirectbr with no destinations", &
I);
614 "Undefined result: extractelement index out of range", &I);
621 "Undefined result: insertelement index out of range", &I);
628 "Unusual: unreachable immediately preceded by instruction without "
640 Value *Lint::findValue(
Value *V,
bool OffsetOk)
const {
642 return findValueImpl(V, OffsetOk, Visited);
646 Value *Lint::findValueImpl(
Value *V,
bool OffsetOk,
649 if (!Visited.
insert(V).second)
658 if (
LoadInst *
L = dyn_cast<LoadInst>(V)) {
663 if (!VisitedBlocks.
insert(BB).second)
667 return findValueImpl(U, OffsetOk, Visited);
668 if (BBI != BB->
begin())
break;
673 }
else if (
PHINode *PN = dyn_cast<PHINode>(V)) {
674 if (
Value *W = PN->hasConstantValue())
676 return findValueImpl(W, OffsetOk, Visited);
677 }
else if (
CastInst *CI = dyn_cast<CastInst>(V)) {
678 if (CI->isNoopCast(*DL))
679 return findValueImpl(CI->getOperand(0), OffsetOk, Visited);
684 return findValueImpl(W, OffsetOk, Visited);
685 }
else if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
689 CE->getOperand(0)->getType(),
CE->getType(),
691 return findValueImpl(
CE->getOperand(0), OffsetOk, Visited);
692 }
else if (
CE->getOpcode() == Instruction::ExtractValue) {
696 return findValueImpl(W, OffsetOk, Visited);
701 if (
Instruction *Inst = dyn_cast<Instruction>(V)) {
703 return findValueImpl(W, OffsetOk, Visited);
704 }
else if (
auto *
C = dyn_cast<Constant>(V)) {
707 return findValueImpl(W, OffsetOk, Visited);
728 Lint *V =
new Lint();
737 Lint *V =
new Lint();
739 PM.
run(const_cast<Module&>(M));
unsigned getAlignment() const
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type (if unknown returns 0).
bool hasNoAliasAttr() const
Return true if this argument has the noalias attribute on it in its containing function.
The two locations precisely alias each other.
Return a value (possibly void), from a function.
void computeKnownBits(const Value *V, APInt &KnownZero, APInt &KnownOne, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
A parsed version of the target data layout string in and methods for querying it. ...
void lintModule(const Module &M)
Check a module.
BasicBlock * getUniquePredecessor()
Return the predecessor of this block if it has a unique predecessor block.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVM Argument representation.
Base class for instruction visitors.
A Module instance is used to store all the information related to an LLVM module. ...
The two locations alias, but only due to a partial overlap.
This class represents a function call, abstracting a target machine's calling convention.
cl::opt< unsigned > DefMaxInstsToScan
The default number of maximum instructions to scan in the block, used by FindAvailableLoadedValue().
void lintFunction(const Function &F)
lintFunction - Check a function for errors, printing messages on stderr.
Statically lint checks LLVM false
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of .assume calls within a function.
This class wraps the llvm.memset intrinsic.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction & front() const
An instruction for reading from memory.
INITIALIZE_PASS_BEGIN(Lint,"lint","Statically lint-checks LLVM IR", false, true) INITIALIZE_PASS_END(Lint
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
unsigned arg_size() const
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
iterator begin()
Instruction iterator methods.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
void add(Pass *P) override
Add a pass to the queue of passes to run.
struct fuzzer::@269 Flags
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
This is the base class for all instructions that perform data casts.
This class wraps the llvm.memmove intrinsic.
ValTy * getCalledValue() const
getCalledValue - Return the pointer to function that is being called.
bool isCall() const
isCall - true if a CallInst is enclosed.
static bool isNoopCast(Instruction::CastOps Opcode, Type *SrcTy, Type *DstTy, Type *IntPtrTy)
A no-op cast is one that can be effected without changing any bits.
Windows NT (Windows on ARM)
This file implements a class to represent arbitrary precision integral constant values and operations...
Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Attempt to fold the constant using the specified DataLayout.
A constant value that is initialized with an expression using other constant values.
Class to represent function types.
CallingConv::ID getCallingConv() const
getCallingConv/setCallingConv - get or set the calling convention of the call.
VectorType * getType() const
Overload to return most specific vector type.
bool hasStructRetAttr() const
Return true if this argument has the sret attribute on it in its containing function.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
An instruction for storing to memory.
Value * FindAvailableLoadedValue(LoadInst *Load, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan=DefMaxInstsToScan, AliasAnalysis *AA=nullptr, bool *IsLoadCSE=nullptr)
Scan backwards to see if we have the value of the given load available locally within a small number ...
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Type * getElementType() const
PassManager manages ModulePassManagers.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
MinAlign - A and B are either alignments or offsets.
This instruction inserts a single (scalar) element into a VectorType value.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This function has undefined behavior.
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Indirect Branch Instruction.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool isZeroValue() const
Return true if the value is negative zero or null value.
bool doesNotReturn() const
Determine if the function cannot return.
AliasResult
The possible results of an alias query.
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
uint64_t getNumElements() const
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
Value * getPointerOperand()
self_iterator getIterator()
unsigned getIntegerBitWidth() const
Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
FunctionPassManager manages FunctionPasses and BasicBlockPassManagers.
bool isPointerTy() const
True if this is an instance of PointerType.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This class represents the va_arg llvm instruction, which returns an argument of the specified type gi...
bool run(Module &M)
run - Execute all of the passes scheduled for execution.
Value * GetUnderlyingObject(Value *V, const DataLayout &DL, unsigned MaxLookup=6)
This method strips off any GEP address adjustments and pointer casts from the specified value...
User::op_iterator arg_iterator
arg_iterator - The type of iterator to use when looping over actual arguments at this call site...
Value * FindInsertedValue(Value *V, ArrayRef< unsigned > idx_range, Instruction *InsertBefore=nullptr)
Given an aggregrate and an sequence of indices, see if the scalar value indexed is already around as ...
FunctionPass * createLintPass()
Create a lint pass.
Iterator for intrusive lists based on ilist_node.
This is the shared class of boolean and integer constants.
InstrTy * getInstruction() const
Value * getDest() const
This is just like getRawDest, but it strips off any cast instructions that feed it, giving the original input.
ValTy * getArgument(unsigned ArgNo) const
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Provides information about what library functions are available for the current target.
Value * getLength() const
void initializeLintPass(PassRegistry &)
This class wraps the llvm.memcpy intrinsic.
const BasicBlock & getEntryBlock() const
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Class to represent vector types.
Class for arbitrary precision integers.
void setPreservesAll()
Set by analyses that do not transform their input at all.
Value * getSource() const
This is just like getRawSource, but it strips off any cast instructions that feed it...
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
unsigned getAlignment() const
Return the alignment of the access that is being performed.
This file provides utility analysis objects describing memory locations.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool hasLocalLinkage() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
const Value * getArraySize() const
Get the number of elements allocated.
This class implements an extremely fast bulk output stream that can only output to a stream...
Value * SimplifyInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const DominatorTree *DT=nullptr, AssumptionCache *AC=nullptr)
See if we can compute a simplified version of this instruction.
Legacy analysis pass which computes a DominatorTree.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Value * getPointerOperand()
unsigned getNumDestinations() const
return the number of possible destinations in this indirectbr instruction.
Statically lint checks LLVM IR
const BasicBlock * getParent() const
A wrapper class for inspecting calls to intrinsic functions.
an instruction to allocate memory on the stack