Fix PR575, patch provided by John Mellor-Crummey. Thanks!
[oota-llvm.git] / lib / Transforms / IPO / LowerSetJmp.cpp
index f18fb929b3428175fface1e48fbf3220cc980186..c040025115bdb5e0a9f5f09e2cd2faefade9e708 100644 (file)
@@ -1,10 +1,10 @@
 //===- LowerSetJmp.cpp - Code pertaining to lowering set/long jumps -------===//
-// 
+//
 //                     The LLVM Compiler Infrastructure
 //
 // This file was developed by the LLVM research group and is distributed under
 // the University of Illinois Open Source License. See LICENSE.TXT for details.
-// 
+//
 //===----------------------------------------------------------------------===//
 //
 //  This file implements the lowering of setjmp and longjmp to use the
@@ -33,6 +33,7 @@
 // pass invokable via the "opt" command at will.
 //===----------------------------------------------------------------------===//
 
+#include "llvm/Transforms/IPO.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Instructions.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/CFG.h"
 #include "llvm/Support/InstVisitor.h"
-#include "llvm/Transforms/Utils/DemoteRegToStack.h"
-#include "Support/DepthFirstIterator.h"
-#include "Support/Statistic.h"
-#include "Support/StringExtras.h"
-#include "Support/VectorExtras.h"
-
-namespace llvm {
+#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/VectorExtras.h"
+using namespace llvm;
 
 namespace {
   Statistic<> LongJmpsTransformed("lowersetjmp",
@@ -60,11 +60,8 @@ namespace {
                                  "Number of invokes modified");
 
   //===--------------------------------------------------------------------===//
-  // LowerSetJmp pass implementation. This is subclassed from the "Pass"
-  // class because it works on a module as a whole, not a function at a
-  // time.
-
-  class LowerSetJmp : public Pass,
+  // LowerSetJmp pass implementation.
+  class LowerSetJmp : public ModulePass,
                       public InstVisitor<LowerSetJmp> {
     // LLVM library functions...
     Function* InitSJMap;        // __llvm_sjljeh_init_setjmpmap
@@ -119,7 +116,7 @@ namespace {
     void visitReturnInst(ReturnInst& RI);
     void visitUnwindInst(UnwindInst& UI);
 
-    bool run(Module& M);
+    bool runOnModule(Module& M);
     bool doInitialization(Module& M);
   };
 
@@ -129,8 +126,7 @@ namespace {
 // run - Run the transformation on the program. We grab the function
 // prototypes for longjmp and setjmp. If they are used in the program,
 // then we can go directly to the places they're at and transform them.
-bool LowerSetJmp::run(Module& M)
-{
+bool LowerSetJmp::runOnModule(Module& M) {
   bool Changed = false;
 
   // These are what the functions are called.
@@ -208,32 +204,32 @@ bool LowerSetJmp::doInitialization(Module& M)
 
   // void __llvm_sjljeh_init_setjmpmap(void**)
   InitSJMap = M.getOrInsertFunction("__llvm_sjljeh_init_setjmpmap",
-                                    Type::VoidTy, SBPPTy, 0); 
+                                    Type::VoidTy, SBPPTy, NULL);
   // void __llvm_sjljeh_destroy_setjmpmap(void**)
   DestroySJMap = M.getOrInsertFunction("__llvm_sjljeh_destroy_setjmpmap",
-                                       Type::VoidTy, SBPPTy, 0);
+                                       Type::VoidTy, SBPPTy, NULL);
 
   // void __llvm_sjljeh_add_setjmp_to_map(void**, void*, unsigned)
   AddSJToMap = M.getOrInsertFunction("__llvm_sjljeh_add_setjmp_to_map",
                                      Type::VoidTy, SBPPTy, SBPTy,
-                                     Type::UIntTy, 0);
+                                     Type::UIntTy, NULL);
 
   // void __llvm_sjljeh_throw_longjmp(int*, int)
   ThrowLongJmp = M.getOrInsertFunction("__llvm_sjljeh_throw_longjmp",
-                                       Type::VoidTy, SBPTy, Type::IntTy, 0);
+                                       Type::VoidTy, SBPTy, Type::IntTy, NULL);
 
   // unsigned __llvm_sjljeh_try_catching_longjmp_exception(void **)
   TryCatchLJ =
     M.getOrInsertFunction("__llvm_sjljeh_try_catching_longjmp_exception",
-                          Type::UIntTy, SBPPTy, 0);
+                          Type::UIntTy, SBPPTy, NULL);
 
   // bool __llvm_sjljeh_is_longjmp_exception()
   IsLJException = M.getOrInsertFunction("__llvm_sjljeh_is_longjmp_exception",
-                                        Type::BoolTy, 0);
+                                        Type::BoolTy, NULL);
 
   // int __llvm_sjljeh_get_longjmp_value()
   GetLJValue = M.getOrInsertFunction("__llvm_sjljeh_get_longjmp_value",
-                                     Type::IntTy, 0);
+                                     Type::IntTy, NULL);
   return true;
 }
 
@@ -242,8 +238,7 @@ bool LowerSetJmp::doInitialization(Module& M)
 // "llvm.{setjmp,longjmp}" functions and none of the setjmp/longjmp error
 // handling functions (beginning with __llvm_sjljeh_...they don't throw
 // exceptions).
-bool LowerSetJmp::IsTransformableFunction(const std::string& Name)
-{
+bool LowerSetJmp::IsTransformableFunction(const std::string& Name) {
   std::string SJLJEh("__llvm_sjljeh");
 
   if (Name.size() > SJLJEh.size())
@@ -277,9 +272,17 @@ void LowerSetJmp::TransformLongJmpCall(CallInst* Inst)
   else
     new UnwindInst(Inst);
 
-  // Remove all insts after the branch/unwind inst.
-  Inst->getParent()->getInstList().erase(Inst,
-                                       Inst->getParent()->getInstList().end());
+  // Remove all insts after the branch/unwind inst.  Go from back to front to
+  // avoid replaceAllUsesWith if possible.
+  BasicBlock *BB = Inst->getParent();
+  Instruction *Removed;
+  do {
+    Removed = &BB->back();
+    // If the removed instructions have any users, replace them now.
+    if (!Removed->use_empty())
+      Removed->replaceAllUsesWith(UndefValue::get(Removed->getType()));
+    Removed->eraseFromParent();
+  } while (Removed != Inst);
 
   ++LongJmpsTransformed;
 }
@@ -356,7 +359,7 @@ LowerSetJmp::SwitchValuePair LowerSetJmp::GetSJSwitch(Function* Func,
     CallInst(TryCatchLJ, make_vector<Value*>(GetSetJmpMap(Func), 0), "SJNum");
   DecisionBBIL.push_back(SJNum);
 
-  SwitchInst* SI = new SwitchInst(SJNum, Rethrow, DecisionBB);
+  SwitchInst* SI = new SwitchInst(SJNum, Rethrow, 0, DecisionBB);
   return SwitchValMap[Func] = SwitchValuePair(SI, LJVal);
 }
 
@@ -391,7 +394,7 @@ void LowerSetJmp::TransformSetJmpCall(CallInst* Inst)
   // instructions after the call.
   for (BasicBlock::iterator I = ++BasicBlock::iterator(Inst), E = ABlock->end();
        I != E; ++I)
-    InstrsAfterCall.insert(I);    
+    InstrsAfterCall.insert(I);
 
   for (BasicBlock::iterator II = ABlock->begin();
        II != BasicBlock::iterator(Inst); ++II)
@@ -411,12 +414,10 @@ void LowerSetJmp::TransformSetJmpCall(CallInst* Inst)
   BasicBlock* SetJmpContBlock = ABlock->splitBasicBlock(Inst);
   assert(SetJmpContBlock && "Couldn't split setjmp BB!!");
 
-  SetJmpContBlock->setName("SetJmpContBlock");
+  SetJmpContBlock->setName(ABlock->getName()+"SetJmpCont");
 
-  // Reposition the split BB in the BB list to make things tidier.
-  Func->getBasicBlockList().remove(SetJmpContBlock);
-  Func->getBasicBlockList().insert(++Function::iterator(ABlock),
-                                   SetJmpContBlock);
+  // Add the SetJmpContBlock to the set of blocks reachable from a setjmp.
+  DFSBlocks.insert(SetJmpContBlock);
 
   // This PHI node will be in the new block created from the
   // splitBasicBlock call.
@@ -458,19 +459,17 @@ void LowerSetJmp::visitCallInst(CallInst& CI)
 
   BasicBlock* NewBB = OldBB->splitBasicBlock(CI);
   assert(NewBB && "Couldn't split BB of \"call\" instruction!!");
+  DFSBlocks.insert(NewBB);
   NewBB->setName("Call2Invoke");
 
-  // Reposition the split BB in the BB list to make things tidier.
   Function* Func = OldBB->getParent();
-  Func->getBasicBlockList().remove(NewBB);
-  Func->getBasicBlockList().insert(++Function::iterator(OldBB), NewBB);
 
   // Construct the new "invoke" instruction.
   TerminatorInst* Term = OldBB->getTerminator();
   std::vector<Value*> Params(CI.op_begin() + 1, CI.op_end());
   InvokeInst* II = new
     InvokeInst(CI.getCalledValue(), NewBB, PrelimBBMap[Func],
-               Params, CI.getName(), Term); 
+               Params, CI.getName(), Term);
 
   // Replace the old call inst with the invoke inst and remove the call.
   CI.replaceAllUsesWith(II);
@@ -497,7 +496,7 @@ void LowerSetJmp::visitInvokeInst(InvokeInst& II)
   if (!DFSBlocks.count(BB)) return;
 
   BasicBlock* NormalBB = II.getNormalDest();
-  BasicBlock* ExceptBB = II.getExceptionalDest();
+  BasicBlock* ExceptBB = II.getUnwindDest();
 
   Function* Func = BB->getParent();
   BasicBlock* NewExceptBB = new BasicBlock("InvokeExcept", Func);
@@ -511,14 +510,13 @@ void LowerSetJmp::visitInvokeInst(InvokeInst& II)
 
   new BranchInst(PrelimBBMap[Func], ExceptBB, IsLJExcept, NewExceptBB);
 
-  II.setExceptionalDest(NewExceptBB);
+  II.setUnwindDest(NewExceptBB);
   ++InvokesTransformed;
 }
 
 // visitReturnInst - We want to destroy the setjmp map upon exit from the
 // function.
-void LowerSetJmp::visitReturnInst(ReturnInst& RI)
-{
+void LowerSetJmp::visitReturnInst(ReturnInst &RI) {
   Function* Func = RI.getParent()->getParent();
   new CallInst(DestroySJMap, make_vector<Value*>(GetSetJmpMap(Func), 0),
                "", &RI);
@@ -526,16 +524,13 @@ void LowerSetJmp::visitReturnInst(ReturnInst& RI)
 
 // visitUnwindInst - We want to destroy the setjmp map upon exit from the
 // function.
-void LowerSetJmp::visitUnwindInst(UnwindInst& UI)
-{
+void LowerSetJmp::visitUnwindInst(UnwindInst &UI) {
   Function* Func = UI.getParent()->getParent();
   new CallInst(DestroySJMap, make_vector<Value*>(GetSetJmpMap(Func), 0),
                "", &UI);
 }
 
-Pass* createLowerSetJmpPass()
-{
+ModulePass *llvm::createLowerSetJmpPass() {
   return new LowerSetJmp();
 }
 
-} // End llvm namespace