61 static unsigned Read = 1;
62 static unsigned Write = 2;
63 static unsigned Callee = 4;
64 static unsigned Branchee = 8;
74 uint64_t Size,
unsigned Align,
98 Value *findValue(
Value *V,
bool OffsetOk)
const;
109 std::string Messages;
127 void WriteValue(
const Value *V) {
129 if (isa<Instruction>(V)) {
130 MessagesStr << *V <<
'\n';
140 void CheckFailed(
const Twine &Message,
143 MessagesStr << Message.
str() <<
"\n";
162 #define Assert(C, M) \
163 do { if (!(C)) { CheckFailed(M); return; } } while (0)
164 #define Assert1(C, M, V1) \
165 do { if (!(C)) { CheckFailed(M, V1); return; } } while (0)
166 #define Assert2(C, M, V1, V2) \
167 do { if (!(C)) { CheckFailed(M, V1, V2); return; } } while (0)
168 #define Assert3(C, M, V1, V2, V3) \
169 do { if (!(C)) { CheckFailed(M, V1, V2, V3); return; } } while (0)
170 #define Assert4(C, M, V1, V2, V3, V4) \
171 do { if (!(C)) { CheckFailed(M, V1, V2, V3, V4); return; } } while (0)
178 AA = &getAnalysis<AliasAnalysis>();
179 DT = &getAnalysis<DominatorTree>();
180 TD = getAnalysisIfAvailable<DataLayout>();
181 TLI = &getAnalysis<TargetLibraryInfo>();
183 dbgs() << MessagesStr.str();
192 "Unusual: Unnamed function with non-local linkage", &
F);
197 void Lint::visitCallSite(
CallSite CS) {
202 0, 0, MemRef::Callee);
204 if (
Function *F = dyn_cast<Function>(findValue(Callee,
false))) {
206 "Undefined behavior: Caller and callee calling convention differ",
210 unsigned NumActualArgs = CS.
arg_size();
213 FT->getNumParams() <= NumActualArgs :
214 FT->getNumParams() == NumActualArgs,
215 "Undefined behavior: Call argument count mismatches callee "
216 "argument count", &
I);
219 "Undefined behavior: Call return type mismatches "
220 "callee return type", &
I);
226 for (; AI != AE; ++AI) {
231 "Undefined behavior: Call argument type mismatches "
232 "callee parameter type", &
I);
239 if (AI != BI && (*BI)->getType()->isPointerTy()) {
243 "Unusual: noalias argument aliases another argument", &I);
249 cast<PointerType>(Formal->
getType())->getElementType();
250 visitMemoryReference(I, Actual, AA->getTypeStoreSize(Ty),
251 TD ?
TD->getABITypeAlignment(Ty) : 0,
252 Ty, MemRef::Read | MemRef::Write);
261 Value *Obj = findValue(*AI,
true);
263 "Undefined behavior: Call with \"tail\" keyword references "
269 switch (II->getIntrinsicID()) {
289 dyn_cast<ConstantInt>(findValue(MCI->
getLength(),
291 if (Len->getValue().isIntN(32))
292 Size = Len->getValue().getZExtValue();
295 "Undefined behavior: memcpy source and destination overlap", &I);
320 "Undefined behavior: va_start called in a non-varargs function",
324 0, 0, MemRef::Read | MemRef::Write);
328 0, 0, MemRef::Write);
334 0, 0, MemRef::Read | MemRef::Write);
342 0, 0, MemRef::Read | MemRef::Write);
347 void Lint::visitCallInst(
CallInst &I) {
348 return visitCallSite(&I);
352 return visitCallSite(&I);
358 "Unusual: Return statement in function with noreturn attribute",
362 Value *Obj = findValue(V,
true);
364 "Unusual: Returning alloca value", &I);
378 Value *UnderlyingObject = findValue(Ptr,
true);
379 Assert1(!isa<ConstantPointerNull>(UnderlyingObject),
380 "Undefined behavior: Null pointer dereference", &I);
381 Assert1(!isa<UndefValue>(UnderlyingObject),
382 "Undefined behavior: Undef pointer dereference", &I);
383 Assert1(!isa<ConstantInt>(UnderlyingObject) ||
384 !cast<ConstantInt>(UnderlyingObject)->isAllOnesValue(),
385 "Unusual: All-ones pointer dereference", &I);
386 Assert1(!isa<ConstantInt>(UnderlyingObject) ||
387 !cast<ConstantInt>(UnderlyingObject)->isOne(),
388 "Unusual: Address one pointer dereference", &I);
390 if (Flags & MemRef::Write) {
391 if (
const GlobalVariable *GV = dyn_cast<GlobalVariable>(UnderlyingObject))
393 "Undefined behavior: Write to read-only memory", &
I);
394 Assert1(!isa<Function>(UnderlyingObject) &&
395 !isa<BlockAddress>(UnderlyingObject),
396 "Undefined behavior: Write to text section", &I);
398 if (Flags & MemRef::Read) {
399 Assert1(!isa<Function>(UnderlyingObject),
400 "Unusual: Load from function body", &I);
401 Assert1(!isa<BlockAddress>(UnderlyingObject),
402 "Undefined behavior: Load from block address", &I);
404 if (Flags & MemRef::Callee) {
405 Assert1(!isa<BlockAddress>(UnderlyingObject),
406 "Undefined behavior: Call to block address", &I);
408 if (Flags & MemRef::Branchee) {
409 Assert1(!isa<Constant>(UnderlyingObject) ||
410 isa<BlockAddress>(UnderlyingObject),
411 "Undefined behavior: Branch to non-blockaddress", &I);
423 unsigned BaseAlign = 0;
425 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Base)) {
426 Type *ATy = AI->getAllocatedType();
427 if (
TD && !AI->isArrayAllocation() && ATy->
isSized())
428 BaseSize =
TD->getTypeAllocSize(ATy);
429 BaseAlign = AI->getAlignment();
430 if (
TD && BaseAlign == 0 && ATy->
isSized())
431 BaseAlign =
TD->getABITypeAlignment(ATy);
435 if (GV->hasDefinitiveInitializer()) {
436 Type *GTy = GV->getType()->getElementType();
438 BaseSize =
TD->getTypeAllocSize(GTy);
439 BaseAlign = GV->getAlignment();
440 if (
TD && BaseAlign == 0 && GTy->
isSized())
441 BaseAlign =
TD->getABITypeAlignment(GTy);
449 (Offset >= 0 && Offset + Size <= BaseSize),
450 "Undefined behavior: Buffer overflow", &I);
454 if (
TD && Align == 0 && Ty && Ty->
isSized())
455 Align =
TD->getABITypeAlignment(Ty);
457 "Undefined behavior: Memory reference address is misaligned", &I);
461 void Lint::visitLoadInst(
LoadInst &I) {
467 void Lint::visitStoreInst(
StoreInst &I) {
477 "Undefined result: xor(undef, undef)", &I);
483 "Undefined result: sub(undef, undef)", &I);
488 dyn_cast<ConstantInt>(findValue(I.
getOperand(1),
false)))
490 "Undefined result: Shift count out of range", &I);
495 dyn_cast<ConstantInt>(findValue(I.
getOperand(1),
false)))
497 "Undefined result: Shift count out of range", &I);
502 dyn_cast<ConstantInt>(findValue(I.
getOperand(1),
false)))
504 "Undefined result: Shift count out of range", &I);
509 if (isa<UndefValue>(V))
515 APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
517 return KnownZero.isAllOnesValue();
533 if (isa<UndefValue>(Elem))
536 APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
538 if (KnownZero.isAllOnesValue())
547 "Undefined behavior: Division by zero", &I);
552 "Undefined behavior: Division by zero", &I);
557 "Undefined behavior: Division by zero", &I);
562 "Undefined behavior: Division by zero", &I);
569 "Pessimization: Static alloca outside of entry block", &
I);
574 void Lint::visitVAArgInst(
VAArgInst &I) {
576 MemRef::Read | MemRef::Write);
584 "Undefined behavior: indirectbr with no destinations", &
I);
592 "Undefined result: extractelement index out of range", &I);
597 dyn_cast<ConstantInt>(findValue(I.
getOperand(2),
600 "Undefined result: insertelement index out of range", &I);
607 "Unusual: unreachable immediately preceded by instruction without "
618 Value *Lint::findValue(
Value *V,
bool OffsetOk)
const {
620 return findValueImpl(V, OffsetOk, Visited);
624 Value *Lint::findValueImpl(
Value *V,
bool OffsetOk,
636 if (
LoadInst *L = dyn_cast<LoadInst>(V)) {
641 if (!VisitedBlocks.
insert(BB))
break;
644 return findValueImpl(U, OffsetOk, Visited);
645 if (BBI != BB->
begin())
break;
650 }
else if (
PHINode *PN = dyn_cast<PHINode>(V)) {
651 if (
Value *W = PN->hasConstantValue())
653 return findValueImpl(W, OffsetOk, Visited);
654 }
else if (
CastInst *CI = dyn_cast<CastInst>(V)) {
657 return findValueImpl(CI->getOperand(0), OffsetOk, Visited);
662 return findValueImpl(W, OffsetOk, Visited);
663 }
else if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
667 CE->getOperand(0)->getType(),
671 return findValueImpl(CE->getOperand(0), OffsetOk, Visited);
672 }
else if (CE->getOpcode() == Instruction::ExtractValue) {
676 return findValueImpl(W, OffsetOk, Visited);
681 if (
Instruction *Inst = dyn_cast<Instruction>(V)) {
683 return findValueImpl(W, OffsetOk, Visited);
684 }
else if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
687 return findValueImpl(W, OffsetOk, Visited);
705 assert(!F.
isDeclaration() &&
"Cannot lint external functions");
708 Lint *V =
new Lint();
717 Lint *V =
new Lint();
719 PM.run(const_cast<Module&>(M));
unsigned getAlignment() const
bool hasNoAliasAttr() const
Return true if this argument has the noalias attribute on it in its containing function.
Pointers differ, but pointees overlap.
void lintModule(const Module &M)
Check a module.
BasicBlock * getUniquePredecessor()
Return this block if it has a unique predecessor block. Otherwise return a null pointer.
static PassRegistry * getPassRegistry()
LLVM Argument representation.
Base class for instruction visitors.
The main container class for the LLVM Intermediate Representation.
unsigned arg_size() const
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout *TD)
void lintFunction(const Function &F)
Statically lint checks LLVM false
DenseSet< const BlockT * > VisitedBlocks
const Function * getParent() const
Return the enclosing method, or null if none.
INITIALIZE_PASS_BEGIN(Lint,"lint","Statically lint-checks LLVM IR", false, true) INITIALIZE_PASS_END(Lint
static IntegerType * getInt64Ty(LLVMContext &C)
ValTy * getArgument(unsigned ArgNo) const
CallingConv::ID getCallingConv() const
void WriteAsOperand(raw_ostream &, const Value *, bool PrintTy=true, const Module *Context=0)
Value * GetUnderlyingObject(Value *V, const DataLayout *TD=0, unsigned MaxLookup=6)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
std::string str() const
str - Return the twine contents as a std::string.
static unsigned getBitWidth(Type *Ty, const DataLayout *TD)
Value * FindInsertedValue(Value *V, ArrayRef< unsigned > idx_range, Instruction *InsertBefore=0)
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
Base class of casting instructions.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
static bool isNoopCast(Instruction::CastOps Opcode, Type *SrcTy, Type *DstTy, Type *IntPtrTy)
Determine if the described cast is a no-op cast.
ID
LLVM Calling Convention Representation.
VectorType * getType() const
bool hasStructRetAttr() const
Return true if this argument has the sret attribute on it in its containing function.
Constant * ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout *TD=0, const TargetLibraryInfo *TLI=0)
CallingConv::ID getCallingConv() const
ValTy * getCalledValue() const
unsigned getNumElements() const
Return the number of elements in the Vector type.
Type * getElementType() const
void ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne, const DataLayout *TD=0, unsigned Depth=0)
User::op_iterator arg_iterator
unsigned getAlignment() const
LLVM Basic Block Representation.
InstrTy * getInstruction() const
LLVM Constant Representation.
bool isZeroValue() const
Return true if the value is negative zero or null value.
bool doesNotReturn() const
Determine if the function cannot return.
Value * getOperand(unsigned i) const
Value * getPointerOperand()
Constant * getAggregateElement(unsigned Elt) const
#define INITIALIZE_AG_DEPENDENCY(depName)
static UndefValue * get(Type *T)
Value * SimplifyInstruction(Instruction *I, const DataLayout *TD=0, const TargetLibraryInfo *TLI=0, const DominatorTree *DT=0)
LLVMContext & getContext() const
All values hold a context through their type.
FunctionPass * createLintPass()
Create a lint pass.
#define Assert1(C, M, V1)
static bool isZero(Value *V, DataLayout *DL)
unsigned getIntegerBitWidth() const
Class for constant integers.
Value * FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan=6, AliasAnalysis *AA=0, MDNode **TBAATag=0)
Value * getLength() const
void initializeLintPass(PassRegistry &)
const BasicBlock & getEntryBlock() const
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
Class for arbitrary precision integers.
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(DefaultAlign), cl::values(clEnumValN(DefaultAlign,"arm-default-align","Generate unaligned accesses only on hardware/OS ""combinations that are known to support them"), clEnumValN(StrictAlign,"arm-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"arm-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
Value * getSource() const
uint64_t MinAlign(uint64_t A, uint64_t B)
bool isDeclaration() const
unsigned getAlignment() const
FunctionType * getFunctionType() const
static uint64_t const UnknownSize
bool hasLocalLinkage() const
LLVM Value Representation.
const Value * getArraySize() const
ItTy prior(ItTy it, Dist n)
Value * getPointerOperand()
unsigned getNumDestinations() const
Statically lint checks LLVM IR
const BasicBlock * getParent() const
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD