From ee5457cbe88b7f691f774de8515d9a94226d1b00 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 8 Sep 2003 19:44:26 +0000 Subject: [PATCH] Eliminate support for the llvm.unwind intrinisic, using the Unwind instruction instead git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8411 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/CBackend/CBackend.cpp | 13 ------- lib/Target/CBackend/Writer.cpp | 13 ------- lib/Target/X86/InstSelectSimple.cpp | 1 - lib/Target/X86/X86ISelSimple.cpp | 1 - lib/Transforms/IPO/PruneEH.cpp | 11 +++--- lib/Transforms/Utils/InlineFunction.cpp | 41 +++++++-------------- lib/Transforms/Utils/SimplifyCFG.cpp | 49 ++++++++++++------------- lib/VMCore/Function.cpp | 3 -- lib/VMCore/Verifier.cpp | 2 - 9 files changed, 44 insertions(+), 90 deletions(-) diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 073ce19189f..0a9c8d1d017 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -1153,19 +1153,6 @@ void CWriter::visitCallInst(CallInst &I) { Out << ")"; return; - case LLVMIntrinsic::unwind: - // The unwind intrinsic calls a control flow transfer out of the current - // function, unwinding the stack until a caller who used the invoke - // instruction is found. In this context, we code generated the invoke - // instruction to add an entry to the top of the jmpbuf_list. Thus, - // here we just have to longjmp to the specified handler. - Out << "if (__llvm_jmpbuf_list == 0) { /* llvm.unwind */\n" - << " printf(\"throw found with no handler!\\n\"); abort();\n" - << " }\n" - << " longjmp(__llvm_jmpbuf_list->buf, 1)"; - return; - - case LLVMIntrinsic::setjmp: case LLVMIntrinsic::sigsetjmp: // This instrinsic should never exist in the program, but until we get diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index 073ce19189f..0a9c8d1d017 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -1153,19 +1153,6 @@ void CWriter::visitCallInst(CallInst &I) { Out << ")"; return; - case LLVMIntrinsic::unwind: - // The unwind intrinsic calls a control flow transfer out of the current - // function, unwinding the stack until a caller who used the invoke - // instruction is found. In this context, we code generated the invoke - // instruction to add an entry to the top of the jmpbuf_list. Thus, - // here we just have to longjmp to the specified handler. - Out << "if (__llvm_jmpbuf_list == 0) { /* llvm.unwind */\n" - << " printf(\"throw found with no handler!\\n\"); abort();\n" - << " }\n" - << " longjmp(__llvm_jmpbuf_list->buf, 1)"; - return; - - case LLVMIntrinsic::setjmp: case LLVMIntrinsic::sigsetjmp: // This instrinsic should never exist in the program, but until we get diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp index 6712d94f324..85708ff2fd4 100644 --- a/lib/Target/X86/InstSelectSimple.cpp +++ b/lib/Target/X86/InstSelectSimple.cpp @@ -1044,7 +1044,6 @@ void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) { addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1); return; - case LLVMIntrinsic::unwind: // llvm.unwind is not supported yet! case LLVMIntrinsic::longjmp: case LLVMIntrinsic::siglongjmp: BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true); diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp index 6712d94f324..85708ff2fd4 100644 --- a/lib/Target/X86/X86ISelSimple.cpp +++ b/lib/Target/X86/X86ISelSimple.cpp @@ -1044,7 +1044,6 @@ void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) { addDirectMem(BuildMI(BB, X86::MOVrm32, 5), TmpReg2).addReg(TmpReg1); return; - case LLVMIntrinsic::unwind: // llvm.unwind is not supported yet! case LLVMIntrinsic::longjmp: case LLVMIntrinsic::siglongjmp: BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true); diff --git a/lib/Transforms/IPO/PruneEH.cpp b/lib/Transforms/IPO/PruneEH.cpp index 41f7f73845c..8be8761b853 100644 --- a/lib/Transforms/IPO/PruneEH.cpp +++ b/lib/Transforms/IPO/PruneEH.cpp @@ -38,7 +38,7 @@ bool PruneEH::runOnSCC(const std::vector &SCC) { // First, check to see if any callees might throw or if there are any external // functions in this SCC: if so, we cannot prune any functions in this SCC. - // If this SCC includes the llvm.unwind intrinsic, we KNOW it throws, so + // If this SCC includes the unwind instruction, we KNOW it throws, so // obviously the SCC might throw. // bool SCCMightThrow = false; @@ -48,10 +48,11 @@ bool PruneEH::runOnSCC(const std::vector &SCC) { std::find(SCC.begin(), SCC.end(), SCC[i]) == SCC.end()) { SCCMightThrow = true; break; } else if (Function *F = SCC[i]->getFunction()) - if (F->isExternal() || // Is external function - F->getIntrinsicID() == LLVMIntrinsic::unwind) {// Is unwind function! - SCCMightThrow = true; break; - } + if (!F->isExternal()) + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) + if (isa(I->getTerminator())) { // Uses unwind! + SCCMightThrow = true; break; + } bool MadeChange = false; diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 864b6ba3db3..17628e22537 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -177,38 +177,13 @@ bool InlineFunction(CallSite CS) { // If we just inlined a call due to an invoke instruction, scan the inlined // function checking for function calls that should now be made into invoke - // instructions, and for llvm.exc.rethrow()'s which should be turned into - // branches. + // instructions, and for unwind's which should be turned into branches. if (InvokeDest) - for (Function::iterator BB = LastBlock, E = Caller->end(); BB != E; ++BB) + for (Function::iterator BB = LastBlock, E = Caller->end(); BB != E; ++BB) { for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { // We only need to check for function calls: inlined invoke instructions // require no special handling... if (CallInst *CI = dyn_cast(I)) { - if (Function *F = CI->getCalledFunction()) - if (unsigned ID = F->getIntrinsicID()) - if (ID == LLVMIntrinsic::unwind) { - // llvm.unwind requires special handling when it gets inlined - // into an invoke site. Once this happens, we know that the - // unwind would cause a control transfer to the invoke exception - // destination, so we can transform it into a direct branch to - // the exception destination. - BranchInst *BI = new BranchInst(InvokeDest, CI); - - // Note that since any instructions after the rethrow/branch are - // dead, we must delete them now (otherwise the terminator we - // just inserted wouldn't be at the end of the basic block!) - BasicBlock *CurBB = BB; - while (&CurBB->back() != BI) { - Instruction *I = &CurBB->back(); - if (!I->use_empty()) - I->replaceAllUsesWith(Constant::getNullValue(I->getType())); - CurBB->getInstList().pop_back(); - } - - break; // Done with this basic block! - } - // Convert this function call into an invoke instruction... // First, split the basic block... @@ -231,6 +206,18 @@ bool InlineFunction(CallSite CS) { } } + if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { + // An UnwindInst requires special handling when it gets inlined into an + // invoke site. Once this happens, we know that the unwind would cause + // a control transfer to the invoke exception destination, so we can + // transform it into a direct branch to the exception destination. + BranchInst *BI = new BranchInst(InvokeDest, UI); + + // Delete the unwind instruction! + UI->getParent()->getInstList().pop_back(); + } + } + // Now that the function is correct, make it a little bit nicer. In // particular, move the basic blocks inserted from the end of the function // into the space made by splitting the source basic block. diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index f47c8405186..1d5e4ec8afb 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -101,32 +101,31 @@ bool SimplifyCFG(BasicBlock *BB) { // 'llvm.unwind'. If so, replace any invoke instructions which use this as an // exception destination with call instructions. // - if (CallInst *CI = dyn_cast(&BB->front())) - if (Function *F = CI->getCalledFunction()) - if (F->getIntrinsicID() == LLVMIntrinsic::unwind) { - std::vector Preds(pred_begin(BB), pred_end(BB)); - while (!Preds.empty()) { - BasicBlock *Pred = Preds.back(); - if (InvokeInst *II = dyn_cast(Pred->getTerminator())) - if (II->getExceptionalDest() == BB) { - // Insert a new branch instruction before the invoke, because this - // is now a fall through... - BranchInst *BI = new BranchInst(II->getNormalDest(), II); - Pred->getInstList().remove(II); // Take out of symbol table - - // Insert the call now... - std::vector Args(II->op_begin()+3, II->op_end()); - CallInst *CI = new CallInst(II->getCalledValue(), Args, - II->getName(), BI); - // If the invoke produced a value, the Call now does instead - II->replaceAllUsesWith(CI); - delete II; - Changed = true; - } - - Preds.pop_back(); - } + if (UnwindInst *UI = dyn_cast(BB->getTerminator())) + if (BB->begin() == BasicBlock::iterator(UI)) { // Empty block? + std::vector Preds(pred_begin(BB), pred_end(BB)); + while (!Preds.empty()) { + BasicBlock *Pred = Preds.back(); + if (InvokeInst *II = dyn_cast(Pred->getTerminator())) + if (II->getExceptionalDest() == BB) { + // Insert a new branch instruction before the invoke, because this + // is now a fall through... + BranchInst *BI = new BranchInst(II->getNormalDest(), II); + Pred->getInstList().remove(II); // Take out of symbol table + + // Insert the call now... + std::vector Args(II->op_begin()+3, II->op_end()); + CallInst *CI = new CallInst(II->getCalledValue(), Args, + II->getName(), BI); + // If the invoke produced a value, the Call now does instead + II->replaceAllUsesWith(CI); + delete II; + Changed = true; + } + + Preds.pop_back(); } + } // Remove basic blocks that have no predecessors... which are unreachable. if (pred_begin(BB) == pred_end(BB) && diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index ccbe4c22448..74098ffc45a 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -203,9 +203,6 @@ unsigned Function::getIntrinsicID() const { if (getName() == "llvm.sigsetjmp") return LLVMIntrinsic::sigsetjmp; if (getName() == "llvm.siglongjmp") return LLVMIntrinsic::siglongjmp; break; - case 'u': - if (getName() == "llvm.unwind") return LLVMIntrinsic::unwind; - break; case 'v': if (getName() == "llvm.va_copy") return LLVMIntrinsic::va_copy; if (getName() == "llvm.va_end") return LLVMIntrinsic::va_end; diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 138542c06fb..2e43d88b85f 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -522,8 +522,6 @@ void Verifier::visitIntrinsicFunctionCall(LLVMIntrinsic::ID ID, CallInst &CI) { case LLVMIntrinsic::va_end: NumArgs = 1; break; case LLVMIntrinsic::va_copy: NumArgs = 2; break; - case LLVMIntrinsic::unwind: NumArgs = 0; break; - case LLVMIntrinsic::setjmp: NumArgs = 1; break; case LLVMIntrinsic::longjmp: NumArgs = 2; break; case LLVMIntrinsic::sigsetjmp: NumArgs = 2; break;