From: David Majnemer Date: Tue, 11 Aug 2015 02:48:30 +0000 (+0000) Subject: [IR] Verify EH pad predecessors X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=106f7b5a0420c76f4c30ca53858be276a285e7ef;p=oota-llvm.git [IR] Verify EH pad predecessors Make sure that an EH pad's predecessors are using their unwind edge to transfer control to the EH pad. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244563 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index b680f6e62f3..863ddc7e2dd 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -392,6 +392,7 @@ private: void visitAllocaInst(AllocaInst &AI); void visitExtractValueInst(ExtractValueInst &EVI); void visitInsertValueInst(InsertValueInst &IVI); + void visitEHPadPredecessors(Instruction &I); void visitLandingPadInst(LandingPadInst &LPI); void visitCatchPadInst(CatchPadInst &CPI); void visitCatchEndPadInst(CatchEndPadInst &CEPI); @@ -2774,23 +2775,54 @@ void Verifier::visitInsertValueInst(InsertValueInst &IVI) { visitInstruction(IVI); } -void Verifier::visitLandingPadInst(LandingPadInst &LPI) { - BasicBlock *BB = LPI.getParent(); +void Verifier::visitEHPadPredecessors(Instruction &I) { + assert(I.isEHPad()); + + BasicBlock *BB = I.getParent(); + Function *F = BB->getParent(); + + Assert(BB != &F->getEntryBlock(), "EH pad cannot be in entry block.", &I); + + if (auto *LPI = dyn_cast(&I)) { + // The landingpad instruction defines its parent as a landing pad block. The + // landing pad block may be branched to only by the unwind edge of an + // invoke. + for (BasicBlock *PredBB : predecessors(BB)) { + const auto *II = dyn_cast(PredBB->getTerminator()); + Assert(II && II->getUnwindDest() == BB && II->getNormalDest() != BB, + "Block containing LandingPadInst must be jumped to " + "only by the unwind edge of an invoke.", + LPI); + } + return; + } + + for (BasicBlock *PredBB : predecessors(BB)) { + TerminatorInst *TI = PredBB->getTerminator(); + if (auto *II = dyn_cast(TI)) + Assert(II->getUnwindDest() == BB && II->getNormalDest() != BB, + "EH pad must be jumped to via an unwind edge", &I, II); + else if (auto *CPI = dyn_cast(TI)) + Assert(CPI->getUnwindDest() == BB && CPI->getNormalDest() != BB, + "EH pad must be jumped to via an unwind edge", &I, CPI); + else if (isa(TI)) + ; + else if (isa(TI)) + ; + else if (isa(TI)) + ; + else + Assert(false, "EH pad must be jumped to via an unwind edge", &I, TI); + } +} +void Verifier::visitLandingPadInst(LandingPadInst &LPI) { // The landingpad instruction is ill-formed if it doesn't have any clauses and // isn't a cleanup. Assert(LPI.getNumClauses() > 0 || LPI.isCleanup(), "LandingPadInst needs at least one clause or to be a cleanup.", &LPI); - // The landingpad instruction defines its parent as a landing pad block. The - // landing pad block may be branched to only by the unwind edge of an invoke. - for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) { - const InvokeInst *II = dyn_cast((*I)->getTerminator()); - Assert(II && II->getUnwindDest() == BB && II->getNormalDest() != BB, - "Block containing LandingPadInst must be jumped to " - "only by the unwind edge of an invoke.", - &LPI); - } + visitEHPadPredecessors(LPI); if (!LandingPadResultTy) LandingPadResultTy = LPI.getType(); @@ -2826,7 +2858,7 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) { } void Verifier::visitCatchPadInst(CatchPadInst &CPI) { - BasicBlock *BB = CPI.getParent(); + visitEHPadPredecessors(CPI); if (!CatchPadResultTy) CatchPadResultTy = CPI.getType(); @@ -2836,6 +2868,7 @@ void Verifier::visitCatchPadInst(CatchPadInst &CPI) { "inside a function.", &CPI); + BasicBlock *BB = CPI.getParent(); Function *F = BB->getParent(); Assert(F->hasPersonalityFn(), "CatchPadInst needs to be in a function with a personality.", &CPI); @@ -2857,8 +2890,9 @@ void Verifier::visitCatchPadInst(CatchPadInst &CPI) { } void Verifier::visitCatchEndPadInst(CatchEndPadInst &CEPI) { - BasicBlock *BB = CEPI.getParent(); + visitEHPadPredecessors(CEPI); + BasicBlock *BB = CEPI.getParent(); Function *F = BB->getParent(); Assert(F->hasPersonalityFn(), "CatchEndPadInst needs to be in a function with a personality.", @@ -2891,6 +2925,8 @@ void Verifier::visitCatchEndPadInst(CatchEndPadInst &CEPI) { } void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) { + visitEHPadPredecessors(CPI); + BasicBlock *BB = CPI.getParent(); if (!CleanupPadResultTy) @@ -2927,8 +2963,9 @@ void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) { } void Verifier::visitTerminatePadInst(TerminatePadInst &TPI) { - BasicBlock *BB = TPI.getParent(); + visitEHPadPredecessors(TPI); + BasicBlock *BB = TPI.getParent(); Function *F = BB->getParent(); Assert(F->hasPersonalityFn(), "TerminatePadInst needs to be in a function with a personality.", diff --git a/test/Feature/exception.ll b/test/Feature/exception.ll index 027f9619470..dbbe7e41edb 100644 --- a/test/Feature/exception.ll +++ b/test/Feature/exception.ll @@ -28,7 +28,11 @@ declare i32 @__gxx_personality_v0(...) define void @cleanupret0() personality i32 (...)* @__gxx_personality_v0 { entry: - br label %bb + br label %try.cont + +try.cont: + invoke void @_Z3quxv() optsize + to label %try.cont unwind label %bb bb: cleanuppad void [i7 4] cleanupret i8 0 unwind label %bb @@ -36,7 +40,11 @@ bb: define void @cleanupret1() personality i32 (...)* @__gxx_personality_v0 { entry: - br label %bb + br label %try.cont + +try.cont: + invoke void @_Z3quxv() optsize + to label %try.cont unwind label %bb bb: cleanuppad void [i7 4] cleanupret void unwind label %bb @@ -60,39 +68,69 @@ bb: define i8 @catchpad() personality i32 (...)* @__gxx_personality_v0 { entry: - br label %bb2 + br label %try.cont + +try.cont: + invoke void @_Z3quxv() optsize + to label %bb unwind label %bb2 bb: - ret i8 %cbv + ret i8 0 bb2: %cbv = catchpad i8 [i7 4] to label %bb unwind label %bb2 } define void @terminatepad0() personality i32 (...)* @__gxx_personality_v0 { entry: - br label %bb + br label %try.cont + +try.cont: + invoke void @_Z3quxv() optsize + to label %try.cont unwind label %bb bb: terminatepad [i7 4] unwind label %bb } define void @terminatepad1() personality i32 (...)* @__gxx_personality_v0 { entry: + br label %try.cont + +try.cont: + invoke void @_Z3quxv() optsize + to label %try.cont unwind label %bb +bb: terminatepad [i7 4] unwind to caller } define void @cleanuppad() personality i32 (...)* @__gxx_personality_v0 { entry: + br label %try.cont + +try.cont: + invoke void @_Z3quxv() optsize + to label %try.cont unwind label %bb +bb: cleanuppad void [i7 4] ret void } define void @catchendpad0() personality i32 (...)* @__gxx_personality_v0 { entry: - br label %bb + br label %try.cont + +try.cont: + invoke void @_Z3quxv() optsize + to label %try.cont unwind label %bb bb: catchendpad unwind label %bb } define void @catchendpad1() personality i32 (...)* @__gxx_personality_v0 { entry: + br label %try.cont + +try.cont: + invoke void @_Z3quxv() optsize + to label %try.cont unwind label %bb +bb: catchendpad unwind to caller }