// Module-level debug info verification...
void verifyTypeRefs();
template <class MapTy>
- void verifyBitPieceExpression(const DbgInfoIntrinsic &I,
- const MapTy &TypeRefs);
+ void verifyDIExpression(const DbgInfoIntrinsic &I, const MapTy &TypeRefs);
void visitUnresolvedTypeRef(const MDString *S, const MDNode *N);
};
} // End anonymous namespace
"Block containg CatchPadInst must be jumped to "
"only by its catchswitch.",
CPI);
+ Assert(BB != CPI->getCatchSwitch()->getUnwindDest(),
+ "Catchswitch cannot unwind to one of its catchpads",
+ CPI->getCatchSwitch(), CPI);
return;
}
}
template <class MapTy>
-void Verifier::verifyBitPieceExpression(const DbgInfoIntrinsic &I,
- const MapTy &TypeRefs) {
+void Verifier::verifyDIExpression(const DbgInfoIntrinsic &I,
+ const MapTy &TypeRefs) {
DILocalVariable *V;
DIExpression *E;
+ const Value *Arg;
+ uint64_t ArgumentTypeSizeInBits = 0;
if (auto *DVI = dyn_cast<DbgValueInst>(&I)) {
+ Arg = DVI->getValue();
+ if (Arg)
+ ArgumentTypeSizeInBits =
+ M->getDataLayout().getTypeAllocSizeInBits(Arg->getType());
V = dyn_cast_or_null<DILocalVariable>(DVI->getRawVariable());
E = dyn_cast_or_null<DIExpression>(DVI->getRawExpression());
} else {
auto *DDI = cast<DbgDeclareInst>(&I);
+ // For declare intrinsics, get the total size of the alloca, to allow
+ // case where the variable may span more than one element.
+ Arg = DDI->getAddress();
+ if (Arg)
+ Arg = Arg->stripPointerCasts();
+ const AllocaInst *AI = dyn_cast_or_null<AllocaInst>(Arg);
+ if (AI) {
+ // We can only say something about constant size allocations
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
+ ArgumentTypeSizeInBits =
+ CI->getLimitedValue() *
+ M->getDataLayout().getTypeAllocSizeInBits(AI->getAllocatedType());
+ }
V = dyn_cast_or_null<DILocalVariable>(DDI->getRawVariable());
E = dyn_cast_or_null<DIExpression>(DDI->getRawExpression());
}
if (!V || !E || !E->isValid())
return;
- // Nothing to do if this isn't a bit piece expression.
- if (!E->isBitPiece())
- return;
-
// The frontend helps out GDB by emitting the members of local anonymous
// unions as artificial local variables with shared storage. When SROA splits
// the storage for artificial local variables that are smaller than the entire
if (!VarSize)
return;
- unsigned PieceSize = E->getBitPieceSize();
- unsigned PieceOffset = E->getBitPieceOffset();
- Assert(PieceSize + PieceOffset <= VarSize,
- "piece is larger than or outside of variable", &I, V, E);
- Assert(PieceSize != VarSize, "piece covers entire variable", &I, V, E);
+ if (E->isBitPiece()) {
+ unsigned PieceSize = E->getBitPieceSize();
+ unsigned PieceOffset = E->getBitPieceOffset();
+ Assert(PieceSize + PieceOffset <= VarSize,
+ "piece is larger than or outside of variable", &I, V, E);
+ Assert(PieceSize != VarSize, "piece covers entire variable", &I, V, E);
+ return;
+ }
+
+ if (!ArgumentTypeSizeInBits)
+ return; // We were unable to determine the size of the argument
+
+ if (E->getNumElements() == 0) {
+ // In the case where the expression is empty, verify the size of the
+ // argument. Doing this in the general case would require looking through
+ // any dereferences that may be in the expression.
+ Assert(ArgumentTypeSizeInBits == VarSize,
+ "size of passed value (" + utostr(ArgumentTypeSizeInBits) +
+ ") does not match size of declared variable (" +
+ utostr(VarSize) + ")",
+ &I, Arg, V, V->getType(), E);
+ } else if (E->getElement(0) == dwarf::DW_OP_deref) {
+ Assert(ArgumentTypeSizeInBits == M->getDataLayout().getPointerSizeInBits(),
+ "the operation of the expression is a deref, but the passed value "
+ "is not pointer sized",
+ &I, Arg, V, V->getType(), E);
+ }
}
void Verifier::visitUnresolvedTypeRef(const MDString *S, const MDNode *N) {
for (const BasicBlock &BB : F)
for (const Instruction &I : BB)
if (auto *DII = dyn_cast<DbgInfoIntrinsic>(&I))
- verifyBitPieceExpression(*DII, TypeRefs);
+ verifyDIExpression(*DII, TypeRefs);
// Return early if all typerefs were resolved.
if (UnresolvedTypeRefs.empty())