mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-19 19:31:50 +00:00
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
This commit is contained in:
parent
da73beac20
commit
ee5457cbe8
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -38,7 +38,7 @@ bool PruneEH::runOnSCC(const std::vector<CallGraphNode *> &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<CallGraphNode *> &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<UnwindInst>(I->getTerminator())) { // Uses unwind!
|
||||
SCCMightThrow = true; break;
|
||||
}
|
||||
|
||||
bool MadeChange = false;
|
||||
|
||||
|
@ -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<CallInst>(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<UnwindInst>(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.
|
||||
|
@ -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<CallInst>(&BB->front()))
|
||||
if (Function *F = CI->getCalledFunction())
|
||||
if (F->getIntrinsicID() == LLVMIntrinsic::unwind) {
|
||||
std::vector<BasicBlock*> Preds(pred_begin(BB), pred_end(BB));
|
||||
while (!Preds.empty()) {
|
||||
BasicBlock *Pred = Preds.back();
|
||||
if (InvokeInst *II = dyn_cast<InvokeInst>(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<Value*> 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<UnwindInst>(BB->getTerminator()))
|
||||
if (BB->begin() == BasicBlock::iterator(UI)) { // Empty block?
|
||||
std::vector<BasicBlock*> Preds(pred_begin(BB), pred_end(BB));
|
||||
while (!Preds.empty()) {
|
||||
BasicBlock *Pred = Preds.back();
|
||||
if (InvokeInst *II = dyn_cast<InvokeInst>(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<Value*> 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) &&
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user