summaryrefslogtreecommitdiff
path: root/lib/IR/Verifier.cpp
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2013-07-31 17:49:08 +0000
committerMatt Arsenault <Matthew.Arsenault@amd.com>2013-07-31 17:49:08 +0000
commit16e4ed5879da57502ea3686c79c63f86994fbe75 (patch)
treeb03848cef153e0fa6d41779770d4b382a62247b4 /lib/IR/Verifier.cpp
parent04ded924f3583438c6633823eddb87761fa73cce (diff)
downloadllvm-16e4ed5879da57502ea3686c79c63f86994fbe75.tar.gz
llvm-16e4ed5879da57502ea3686c79c63f86994fbe75.tar.bz2
llvm-16e4ed5879da57502ea3686c79c63f86994fbe75.tar.xz
Reject bitcasts between address spaces with different sizes
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187506 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/IR/Verifier.cpp')
-rw-r--r--lib/IR/Verifier.cpp124
1 files changed, 104 insertions, 20 deletions
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index b22d211772..d523e42823 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -56,6 +56,7 @@
#include "llvm/DebugInfo.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -128,6 +129,7 @@ namespace {
Module *Mod; // Module we are verifying right now
LLVMContext *Context; // Context within which we are verifying
DominatorTree *DT; // Dominator Tree, caution can be null!
+ const DataLayout *DL;
std::string Messages;
raw_string_ostream MessagesStr;
@@ -152,13 +154,13 @@ namespace {
Verifier()
: FunctionPass(ID), Broken(false),
- action(AbortProcessAction), Mod(0), Context(0), DT(0),
+ action(AbortProcessAction), Mod(0), Context(0), DT(0), DL(0),
MessagesStr(Messages), PersonalityFn(0) {
initializeVerifierPass(*PassRegistry::getPassRegistry());
}
explicit Verifier(VerifierFailureAction ctn)
: FunctionPass(ID), Broken(false), action(ctn), Mod(0),
- Context(0), DT(0), MessagesStr(Messages), PersonalityFn(0) {
+ Context(0), DT(0), DL(0), MessagesStr(Messages), PersonalityFn(0) {
initializeVerifierPass(*PassRegistry::getPassRegistry());
}
@@ -167,6 +169,8 @@ namespace {
Context = &M.getContext();
Finder.reset();
+ DL = getAnalysisIfAvailable<DataLayout>();
+
// We must abort before returning back to the pass manager, or else the
// pass manager may try to run other passes on the broken module.
return abortIfBroken();
@@ -321,6 +325,9 @@ namespace {
void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
const Value *V);
+ void VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy);
+ void VerifyConstantExprBitcastType(const ConstantExpr *CE);
+
void verifyDebugInfo(Module &M);
void WriteValue(const Value *V) {
@@ -487,6 +494,33 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
}
}
+ if (!GV.hasInitializer()) {
+ visitGlobalValue(GV);
+ return;
+ }
+
+ // Walk any aggregate initializers looking for bitcasts between address spaces
+ SmallPtrSet<const Value *, 4> Visited;
+ SmallVector<const Value *, 4> WorkStack;
+ WorkStack.push_back(cast<Value>(GV.getInitializer()));
+
+ while (!WorkStack.empty()) {
+ const Value *V = WorkStack.pop_back_val();
+ if (!Visited.insert(V))
+ continue;
+
+ if (const User *U = dyn_cast<User>(V)) {
+ for (unsigned I = 0, N = U->getNumOperands(); I != N; ++I)
+ WorkStack.push_back(U->getOperand(I));
+ }
+
+ if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
+ VerifyConstantExprBitcastType(CE);
+ if (Broken)
+ return;
+ }
+ }
+
visitGlobalValue(GV);
}
@@ -865,6 +899,52 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
"Attributes 'noinline and alwaysinline' are incompatible!", V);
}
+void Verifier::VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy) {
+ // Get the size of the types in bits, we'll need this later
+ unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
+ unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
+
+ // BitCast implies a no-op cast of type only. No bits change.
+ // However, you can't cast pointers to anything but pointers.
+ Assert1(SrcTy->isPointerTy() == DestTy->isPointerTy(),
+ "Bitcast requires both operands to be pointer or neither", V);
+ Assert1(SrcBitSize == DestBitSize,
+ "Bitcast requires types of same width", V);
+
+ // Disallow aggregates.
+ Assert1(!SrcTy->isAggregateType(),
+ "Bitcast operand must not be aggregate", V);
+ Assert1(!DestTy->isAggregateType(),
+ "Bitcast type must not be aggregate", V);
+
+ // Without datalayout, assume all address spaces are the same size.
+ // Don't check if both types are not pointers.
+ // Skip casts between scalars and vectors.
+ if (!DL ||
+ !SrcTy->isPtrOrPtrVectorTy() ||
+ !DestTy->isPtrOrPtrVectorTy() ||
+ SrcTy->isVectorTy() != DestTy->isVectorTy()) {
+ return;
+ }
+
+ unsigned SrcAS = SrcTy->getPointerAddressSpace();
+ unsigned DstAS = DestTy->getPointerAddressSpace();
+
+ unsigned SrcASSize = DL->getPointerSizeInBits(SrcAS);
+ unsigned DstASSize = DL->getPointerSizeInBits(DstAS);
+ Assert1(SrcASSize == DstASSize,
+ "Bitcasts between pointers of different address spaces must have "
+ "the same size pointers, otherwise use PtrToInt/IntToPtr.", V);
+}
+
+void Verifier::VerifyConstantExprBitcastType(const ConstantExpr *CE) {
+ if (CE->getOpcode() == Instruction::BitCast) {
+ Type *SrcTy = CE->getOperand(0)->getType();
+ Type *DstTy = CE->getType();
+ VerifyBitcastType(CE, DstTy, SrcTy);
+ }
+}
+
bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) {
if (Attrs.getNumSlots() == 0)
return true;
@@ -1349,26 +1429,9 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) {
}
void Verifier::visitBitCastInst(BitCastInst &I) {
- // Get the source and destination types
Type *SrcTy = I.getOperand(0)->getType();
Type *DestTy = I.getType();
-
- // Get the size of the types in bits, we'll need this later
- unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
- unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
-
- // BitCast implies a no-op cast of type only. No bits change.
- // However, you can't cast pointers to anything but pointers.
- Assert1(SrcTy->isPointerTy() == DestTy->isPointerTy(),
- "Bitcast requires both operands to be pointer or neither", &I);
- Assert1(SrcBitSize == DestBitSize, "Bitcast requires types of same width",&I);
-
- // Disallow aggregates.
- Assert1(!SrcTy->isAggregateType(),
- "Bitcast operand must not be aggregate", &I);
- Assert1(!DestTy->isAggregateType(),
- "Bitcast type must not be aggregate", &I);
-
+ VerifyBitcastType(&I, DestTy, SrcTy);
visitInstruction(I);
}
@@ -1992,6 +2055,27 @@ void Verifier::visitInstruction(Instruction &I) {
Assert1((i + 1 == e && isa<CallInst>(I)) ||
(i + 3 == e && isa<InvokeInst>(I)),
"Cannot take the address of an inline asm!", &I);
+ } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) {
+ if (CE->getType()->isPtrOrPtrVectorTy()) {
+ // If we have a ConstantExpr pointer, we need to see if it came from an
+ // illegal bitcast (inttoptr <constant int> )
+ SmallVector<const ConstantExpr *, 4> Stack;
+ SmallPtrSet<const ConstantExpr *, 4> Visited;
+ Stack.push_back(CE);
+
+ while (!Stack.empty()) {
+ const ConstantExpr *V = Stack.pop_back_val();
+ if (!Visited.insert(V))
+ continue;
+
+ VerifyConstantExprBitcastType(V);
+
+ for (unsigned I = 0, N = V->getNumOperands(); I != N; ++I) {
+ if (ConstantExpr *Op = dyn_cast<ConstantExpr>(V->getOperand(I)))
+ Stack.push_back(Op);
+ }
+ }
+ }
}
}