/// \brief Track unresolved string-based type references.
SmallDenseMap<const MDString *, const MDNode *, 32> UnresolvedTypeRefs;
- /// \brief The result type for a catchpad.
- Type *CatchPadResultTy;
-
- /// \brief The result type for a cleanuppad.
- Type *CleanupPadResultTy;
-
/// \brief The result type for a landingpad.
Type *LandingPadResultTy;
public:
explicit Verifier(raw_ostream &OS)
- : VerifierSupport(OS), Context(nullptr), CatchPadResultTy(nullptr),
- CleanupPadResultTy(nullptr), LandingPadResultTy(nullptr),
+ : VerifierSupport(OS), Context(nullptr), LandingPadResultTy(nullptr),
SawFrameEscape(false) {}
bool verify(const Function &F) {
// FIXME: We strip const here because the inst visitor strips const.
visit(const_cast<Function &>(F));
InstsInThisBlock.clear();
- CatchPadResultTy = nullptr;
- CleanupPadResultTy = nullptr;
LandingPadResultTy = nullptr;
SawFrameEscape = false;
void visitCatchPadInst(CatchPadInst &CPI);
void visitCatchEndPadInst(CatchEndPadInst &CEPI);
void visitCleanupPadInst(CleanupPadInst &CPI);
+ void visitCleanupEndPadInst(CleanupEndPadInst &CEPI);
void visitCleanupReturnInst(CleanupReturnInst &CRI);
void visitTerminatePadInst(TerminatePadInst &TPI);
Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags",
&N);
+ if (N.isDefinition())
+ Assert(N.isDistinct(), "subprogram definitions must be distinct", &N);
+
auto *F = N.getFunction();
if (!F)
return;
}
// Visit metadata attachments.
- for (const auto &I : MDs)
+ for (const auto &I : MDs) {
+ // Verify that the attachment is legal.
+ switch (I.first) {
+ default:
+ break;
+ case LLVMContext::MD_dbg:
+ Assert(isa<DISubprogram>(I.second),
+ "function !dbg attachment must be a subprogram", &F, I.second);
+ break;
+ }
+
+ // Verify the metadata itself.
visitMDNode(*I.second);
+ }
}
// If this function is actually an intrinsic, verify that it is only used in
;
else if (isa<CleanupReturnInst>(TI))
;
+ else if (isa<CleanupEndPadInst>(TI))
+ ;
else if (isa<TerminatePadInst>(TI))
;
else
void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
visitEHPadPredecessors(CPI);
- if (!CatchPadResultTy)
- CatchPadResultTy = CPI.getType();
- else
- Assert(CatchPadResultTy == CPI.getType(),
- "The catchpad instruction should have a consistent result type "
- "inside a function.",
- &CPI);
-
BasicBlock *BB = CPI.getParent();
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
"CatchPadInst not the first non-PHI instruction in the block.",
&CPI);
+ if (!BB->getSinglePredecessor())
+ for (BasicBlock *PredBB : predecessors(BB)) {
+ Assert(!isa<CatchPadInst>(PredBB->getTerminator()),
+ "CatchPadInst with CatchPadInst predecessor cannot have any other "
+ "predecessors.",
+ &CPI);
+ }
+
BasicBlock *UnwindDest = CPI.getUnwindDest();
Instruction *I = UnwindDest->getFirstNonPHI();
Assert(
BasicBlock *BB = CPI.getParent();
- if (!CleanupPadResultTy)
- CleanupPadResultTy = CPI.getType();
- else
- Assert(CleanupPadResultTy == CPI.getType(),
- "The cleanuppad instruction should have a consistent result type "
- "inside a function.",
- &CPI);
-
Function *F = BB->getParent();
Assert(F->hasPersonalityFn(),
"CleanupPadInst needs to be in a function with a personality.", &CPI);
"CleanupPadInst not the first non-PHI instruction in the block.",
&CPI);
+ User *FirstUser = nullptr;
+ BasicBlock *FirstUnwindDest = nullptr;
+ for (User *U : CPI.users()) {
+ BasicBlock *UnwindDest;
+ if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(U)) {
+ UnwindDest = CRI->getUnwindDest();
+ } else {
+ UnwindDest = cast<CleanupEndPadInst>(U)->getUnwindDest();
+ }
+
+ if (!FirstUser) {
+ FirstUser = U;
+ FirstUnwindDest = UnwindDest;
+ } else {
+ Assert(UnwindDest == FirstUnwindDest,
+ "Cleanuprets/cleanupendpads from the same cleanuppad must "
+ "have the same unwind destination",
+ FirstUser, U);
+ }
+ }
+
visitInstruction(CPI);
}
+void Verifier::visitCleanupEndPadInst(CleanupEndPadInst &CEPI) {
+ visitEHPadPredecessors(CEPI);
+
+ BasicBlock *BB = CEPI.getParent();
+ Function *F = BB->getParent();
+ Assert(F->hasPersonalityFn(),
+ "CleanupEndPadInst needs to be in a function with a personality.",
+ &CEPI);
+
+ // The cleanupendpad instruction must be the first non-PHI instruction in the
+ // block.
+ Assert(BB->getFirstNonPHI() == &CEPI,
+ "CleanupEndPadInst not the first non-PHI instruction in the block.",
+ &CEPI);
+
+ if (BasicBlock *UnwindDest = CEPI.getUnwindDest()) {
+ Instruction *I = UnwindDest->getFirstNonPHI();
+ Assert(
+ I->isEHPad() && !isa<LandingPadInst>(I),
+ "CleanupEndPad must unwind to an EH block which is not a landingpad.",
+ &CEPI);
+ }
+
+ visitTerminatorInst(CEPI);
+}
+
void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) {
if (BasicBlock *UnwindDest = CRI.getUnwindDest()) {
Instruction *I = UnwindDest->getFirstNonPHI();
case IITDescriptor::Void: return !Ty->isVoidTy();
case IITDescriptor::VarArg: return true;
case IITDescriptor::MMX: return !Ty->isX86_MMXTy();
+ case IITDescriptor::Token: return !Ty->isTokenTy();
case IITDescriptor::Metadata: return !Ty->isMetadataTy();
case IITDescriptor::Half: return !Ty->isHalfTy();
case IITDescriptor::Float: return !Ty->isFloatTy();
"gc.relocate: relocating a pointer shouldn't change its address space", CS);
break;
}
+ case Intrinsic::eh_exceptionpointer: {
+ Assert(isa<CatchPadInst>(CS.getArgOperand(0)),
+ "eh.exceptionpointer argument must be a catchpad", CS);
+ break;
+ }
};
}
for (auto *CU : CUs->operands())
if (auto Ts = cast<DICompileUnit>(CU)->getRetainedTypes())
for (DIType *Op : Ts)
- if (auto *T = dyn_cast<DICompositeType>(Op))
+ if (auto *T = dyn_cast_or_null<DICompositeType>(Op))
if (auto *S = T->getRawIdentifier()) {
UnresolvedTypeRefs.erase(S);
TypeRefs.insert(std::make_pair(S, T));