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
This commit is contained in:
Matt Arsenault
2013-07-31 17:49:08 +00:00
parent 04ded924f3
commit 16e4ed5879
11 changed files with 219 additions and 36 deletions

View File

@ -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);
}
}
}
}
}