From 42c9fd02c2e5f782133f6f340344b150b53c927f Mon Sep 17 00:00:00 2001 From: Mikael Holmen Date: Tue, 3 Oct 2017 06:03:49 +0000 Subject: [PATCH] [Lint] Avoid failed assertion by fetching the proper pointer type Summary: When checking if a constant expression is a noop cast we fetched the IntPtrType by doing DL->getIntPtrType(V->getType())). However, there can be cases where V doesn't return a pointer, and then getIntPtrType() triggers an assertion. Now we pass DataLayout to isNoopCast so the method itself can determine what the IntPtrType is. Reviewers: arsenm Reviewed By: arsenm Subscribers: wdng, llvm-commits Differential Revision: https://reviews.llvm.org/D37894 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314763 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/InstrTypes.h | 8 ++++++ lib/Analysis/Lint.cpp | 2 +- lib/IR/Instructions.cpp | 28 ++++++++++++------- .../Lint/noop-cast-expr-no-pointer.ll | 23 +++++++++++++++ 4 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 test/Analysis/Lint/noop-cast-expr-no-pointer.ll diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index d749077fd34..59a71e5098f 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -789,6 +789,14 @@ public: Type *IntPtrTy ///< Integer type corresponding to Ptr types ); + /// @brief Determine if the described cast is a no-op cast. + static bool isNoopCast( + Instruction::CastOps Opcode, ///< Opcode of cast + Type *SrcTy, ///< SrcTy of cast + Type *DstTy, ///< DstTy of cast + const DataLayout &DL ///< DataLayout to get the Int Ptr type from. + ); + /// @brief Determine if this cast is a no-op cast. bool isNoopCast( Type *IntPtrTy ///< Integer type corresponding to pointer diff --git a/lib/Analysis/Lint.cpp b/lib/Analysis/Lint.cpp index ada600a69b8..ae92f502f5c 100644 --- a/lib/Analysis/Lint.cpp +++ b/lib/Analysis/Lint.cpp @@ -683,7 +683,7 @@ Value *Lint::findValueImpl(Value *V, bool OffsetOk, if (Instruction::isCast(CE->getOpcode())) { if (CastInst::isNoopCast(Instruction::CastOps(CE->getOpcode()), CE->getOperand(0)->getType(), CE->getType(), - DL->getIntPtrType(V->getType()))) + *DL)) return findValueImpl(CE->getOperand(0), OffsetOk, Visited); } else if (CE->getOpcode() == Instruction::ExtractValue) { ArrayRef Indices = CE->getIndices(); diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 2c49564e328..d6297cb6cae 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -2325,22 +2325,30 @@ bool CastInst::isNoopCast(Instruction::CastOps Opcode, } } +/// @brief Determine if a cast is a no-op. +bool CastInst::isNoopCast(Instruction::CastOps Opcode, + Type *SrcTy, + Type *DestTy, + const DataLayout &DL) { + Type *PtrOpTy = nullptr; + if (Opcode == Instruction::PtrToInt) + PtrOpTy = SrcTy; + else if (Opcode == Instruction::IntToPtr) + PtrOpTy = DestTy; + + Type *IntPtrTy = PtrOpTy ? DL.getIntPtrType(PtrOpTy) : + DL.getIntPtrType(SrcTy->getContext(), 0); + + return isNoopCast(Opcode, SrcTy, DestTy, IntPtrTy); +} + /// @brief Determine if a cast is a no-op. bool CastInst::isNoopCast(Type *IntPtrTy) const { return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy); } bool CastInst::isNoopCast(const DataLayout &DL) const { - Type *PtrOpTy = nullptr; - if (getOpcode() == Instruction::PtrToInt) - PtrOpTy = getOperand(0)->getType(); - else if (getOpcode() == Instruction::IntToPtr) - PtrOpTy = getType(); - - Type *IntPtrTy = - PtrOpTy ? DL.getIntPtrType(PtrOpTy) : DL.getIntPtrType(getContext(), 0); - - return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy); + return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), DL); } /// This function determines if a pair of casts can be eliminated and what diff --git a/test/Analysis/Lint/noop-cast-expr-no-pointer.ll b/test/Analysis/Lint/noop-cast-expr-no-pointer.ll new file mode 100644 index 00000000000..b9258711428 --- /dev/null +++ b/test/Analysis/Lint/noop-cast-expr-no-pointer.ll @@ -0,0 +1,23 @@ +; RUN: opt -lint < %s + +; lint shouldn't crash on any of the below functions + +@g_1 = external global [3 x i32] +@g_2 = external global [2 x i32] + +define void @test1() { +entry: + tail call void @f1(i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @g_2, i64 0, i64 0), i32* getelementptr inbounds ([3 x i32], [3 x i32]* @g_1, i64 0, i64 1)) to i16)) + ret void +} + +declare void @f1(i16) + +define void @test2() { + tail call void inttoptr (i64 sext (i32 ptrtoint (void ()* @f2 to i32) to i64) to void ()*)() + + ret void +} + +declare void @f2() + -- 2.40.0