[llvm-commits] [dragonegg] r138447 - in /dragonegg/trunk: include/dragonegg/Internals.h src/Convert.cpp

Duncan Sands baldrick at free.fr
Wed Aug 24 10:58:02 PDT 2011


Author: baldrick
Date: Wed Aug 24 12:58:01 2011
New Revision: 138447

URL: http://llvm.org/viewvc/llvm-project?rev=138447&view=rev
Log:
Move to the new exception handling scheme: landingpad and resume instructions
rather than eh.exception, eh.selector and explicit _Unwind_Resume calls.  Based
on a patch by Bill Wendling.

Modified:
    dragonegg/trunk/include/dragonegg/Internals.h
    dragonegg/trunk/src/Convert.cpp

Modified: dragonegg/trunk/include/dragonegg/Internals.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Internals.h?rev=138447&r1=138446&r2=138447&view=diff
==============================================================================
--- dragonegg/trunk/include/dragonegg/Internals.h (original)
+++ dragonegg/trunk/include/dragonegg/Internals.h Wed Aug 24 12:58:01 2011
@@ -332,12 +332,6 @@
   /// run if an exception is thrown in this region).
   SmallVector<BasicBlock *, 16> FailureBlocks;
 
-  /// RewindBB - Block containing code that continues unwinding an exception.
-  BasicBlock *RewindBB;
-
-  /// RewindTmp - Local holding the exception to continue unwinding.
-  AllocaInst *RewindTmp;
-
 public:
   TreeToLLVM(tree_node *fndecl);
   ~TreeToLLVM();
@@ -460,10 +454,6 @@
   /// an exception is thrown in a must-not-throw region.
   void EmitFailureBlocks();
 
-  /// EmitRewindBlock - Emit the block containing code to continue unwinding an
-  /// exception.
-  void EmitRewindBlock();
-
   /// EmitDebugInfo - Return true if debug info is to be emitted for current
   /// function.
   bool EmitDebugInfo();

Modified: dragonegg/trunk/src/Convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=138447&r1=138446&r2=138447&view=diff
==============================================================================
--- dragonegg/trunk/src/Convert.cpp (original)
+++ dragonegg/trunk/src/Convert.cpp Wed Aug 24 12:58:01 2011
@@ -164,8 +164,6 @@
   Fn = 0;
   ReturnBB = 0;
   ReturnOffset = 0;
-  RewindBB = 0;
-  RewindTmp = 0;
 
   if (EmitDebugInfo()) {
     expanded_location Location = expand_location(DECL_SOURCE_LOCATION (fndecl));
@@ -952,7 +950,6 @@
   // Now that phi nodes have been output, emit pending exception handling code.
   EmitLandingPads();
   EmitFailureBlocks();
-  EmitRewindBlock();
 
   if (EmitDebugInfo()) {
     // FIXME: This should be output just before the return call generated above.
@@ -1955,8 +1952,8 @@
 
   // If a GCC post landing pad is shared by several exception handling regions,
   // or if there is a normal edge to it, then create LLVM landing pads for each
-  // eh region.  Calls to eh.exception and eh.selector will then go in the LLVM
-  // landing pad, which branches to the GCC post landing pad.
+  // eh region.  The landing pad instruction will then go in the LLVM landing
+  // pad, which then branches to the GCC post landing pad.
   for (unsigned LPadNo = 1; LPadNo < NormalInvokes.size(); ++LPadNo) {
     // Get the list of invokes for this GCC landing pad.
     SmallVector<InvokeInst *, 8> &InvokesForPad = NormalInvokes[LPadNo];
@@ -2023,15 +2020,12 @@
     BranchInst::Create(PostPad, LPad);
   }
 
-  // Initialize the exception pointer and selector value for each exception
-  // handling region at the start of the corresponding landing pad.  At this
-  // point each exception handling region has its own landing pad, which is
-  // only reachable via the unwind edges of the region's invokes.
-  std::vector<Value*> Args;
-  Function *ExcIntr = Intrinsic::getDeclaration(TheModule,
-                                                Intrinsic::eh_exception);
-  Function *SlctrIntr = Intrinsic::getDeclaration(TheModule,
-                                                  Intrinsic::eh_selector);
+  // Create the landing pad instruction for each exception handling region at
+  // the start of the corresponding landing pad.  At this point each exception
+  // handling region has its own landing pad, which is only reachable via the
+  // unwind edges of the region's invokes.
+  Type *UnwindDataTy = StructType::get(Builder.getInt8PtrTy(),
+                                       Builder.getInt32Ty(), NULL);
   for (unsigned LPadNo = 1; LPadNo < NormalInvokes.size(); ++LPadNo) {
     // Get the list of invokes for this GCC landing pad.
     SmallVector<InvokeInst *, 8> &InvokesForPad = NormalInvokes[LPadNo];
@@ -2050,96 +2044,76 @@
     // Insert instructions at the start of the landing pad, but after any phis.
     Builder.SetInsertPoint(LPad, LPad->getFirstNonPHI());
 
-    // Fetch the exception pointer.
-    Value *ExcPtr = Builder.CreateCall(ExcIntr, "exc_ptr");
-
-    // Store it if made use of elsewhere.
-    if (RegionNo < ExceptionPtrs.size() && ExceptionPtrs[RegionNo])
-      Builder.CreateStore(ExcPtr, ExceptionPtrs[RegionNo]);
-
-    // Get the exception selector.  The first argument is the exception pointer.
-    Args.push_back(ExcPtr);
-
-    // It is followed by the personality function.
+    // Create the landingpad instruction without any clauses.  Clauses are added
+    // below.
     tree personality = DECL_FUNCTION_PERSONALITY(FnDecl);
     if (!personality) {
       assert(function_needs_eh_personality(cfun) == eh_personality_any &&
              "No exception handling personality!");
       personality = lang_hooks.eh_personality();
     }
-    Args.push_back(Builder.CreateBitCast(DECL_LLVM(personality),
-                                         Type::getInt8PtrTy(Context)));
+    LandingPadInst *LPadInst = Builder.CreateLandingPad(UnwindDataTy,
+                                                        DECL_LLVM(personality),
+                                                        0, "exc");
+
+    // Store the exception pointer if made use of elsewhere.
+    if (RegionNo < ExceptionPtrs.size() && ExceptionPtrs[RegionNo]) {
+      Value *ExcPtr = Builder.CreateExtractValue(LPadInst, 0, "exc_ptr");
+      Builder.CreateStore(ExcPtr, ExceptionPtrs[RegionNo]);
+    }
 
-    Constant *CatchAll = TheModule->getGlobalVariable("llvm.eh.catch.all.value");
-    if (!CatchAll) {
-      // The representation of a catch-all is language specific.
-      // TODO: Remove this hack.
-      Constant *Init = 0;
-      StringRef LanguageName = lang_hooks.name;
-      if (LanguageName == "GNU Ada") {
-        StringRef Name = "__gnat_all_others_value";
-        Init = TheModule->getGlobalVariable(Name);
-        if (!Init)
-          Init = new GlobalVariable(*TheModule, ConvertType(integer_type_node),
-                                    /*isConstant*/true,
-                                    GlobalValue::ExternalLinkage,
-                                    /*Initializer*/NULL, Name);
-      } else {
-        // Other languages use a null pointer.
-        Init = Constant::getNullValue(Type::getInt8PtrTy(Context));
-      }
-      CatchAll = new GlobalVariable(*TheModule, Init->getType(), true,
-                                    GlobalVariable::LinkOnceAnyLinkage,
-                                    Init, "llvm.eh.catch.all.value");
-      cast<GlobalVariable>(CatchAll)->setSection("llvm.metadata");
-      AttributeUsedGlobals.insert(CatchAll);
+    // Store the selector value if made use of elsewhere.
+    if (RegionNo < ExceptionFilters.size() && ExceptionFilters[RegionNo]) {
+      Value *Filter = Builder.CreateExtractValue(LPadInst, 1, "filter");
+      Builder.CreateStore(Filter, ExceptionFilters[RegionNo]);
     }
 
-    bool AllCaught = false; // Did we saw a catch-all or no-throw?
-    bool HasCleanup = false; // Did we see a cleanup?
+    // Add clauses to the landing pad instruction.
+    bool AllCaught = false; // Did we see a catch-all or no-throw?
     SmallSet<Constant *, 8> AlreadyCaught; // Typeinfos known caught already.
     for (; region && !AllCaught; region = region->outer)
       switch (region->type) {
       case ERT_ALLOWED_EXCEPTIONS: {
-        // Filter.
-
-        // Push a fake placeholder value for the length.  The real length is
-        // computed below, once we know which typeinfos we are going to use.
-        unsigned LengthIndex = Args.size();
-        Args.push_back(NULL); // Fake length value.
-
-        // Add the type infos.
+        // Filter.  Compute the list of type infos.
         AllCaught = true;
+        std::vector<Constant*> TypeInfos;
         for (tree type = region->u.allowed.type_list; type;
              type = TREE_CHAIN(type)) {
           Constant *TypeInfo = ConvertTypeInfo(TREE_VALUE(type));
-          // No point in permitting a typeinfo to be thrown if we know it can
-          // never reach the filter.
+          // No point in letting a typeinfo through if we know it can't reach
+          // the filter in the first place.
           if (AlreadyCaught.count(TypeInfo))
             continue;
-          Args.push_back(TypeInfo);
+          TypeInfo = TheFolder->CreateBitCast(TypeInfo, Builder.getInt8PtrTy());
+          TypeInfos.push_back(TypeInfo);
           AllCaught = false;
         }
 
-        // The length is one more than the number of typeinfos.
-        Args[LengthIndex] = Builder.getInt32(Args.size() - LengthIndex);
+        // Add the list of typeinfos as a filter clause.
+        ArrayType *FilterTy = ArrayType::get(Builder.getInt8PtrTy(),
+                                             TypeInfos.size());
+        LPadInst->addClause(ConstantArray::get(FilterTy, TypeInfos));
         break;
       }
       case ERT_CLEANUP:
-        HasCleanup = true;
+        LPadInst->setCleanup(true);
         break;
-      case ERT_MUST_NOT_THROW:
-        // Same as a zero-length filter.
+      case ERT_MUST_NOT_THROW: {
+        // Same as a zero-length filter: add an empty filter clause.
+        ArrayType *FilterTy = ArrayType::get(Builder.getInt8PtrTy(), 0);
+        LPadInst->addClause(ConstantArray::get(FilterTy,
+                                               ArrayRef<Constant*>()));
         AllCaught = true;
-        Args.push_back(Builder.getInt32(1));
         break;
+      }
       case ERT_TRY:
         // Catches.
         for (eh_catch c = region->u.eh_try.first_catch; c ; c = c->next_catch)
           if (!c->type_list) {
-            // Catch-all - push a null pointer.
+            // Catch-all - add a null pointer as a catch clause.
+            LPadInst->addClause(Constant::getNullValue(Builder.getInt8PtrTy()));
             AllCaught = true;
-            Args.push_back(Constant::getNullValue(Type::getInt8PtrTy(Context)));
+            break;
           } else {
             // Add the type infos.
             for (tree type = c->type_list; type; type = TREE_CHAIN(type)) {
@@ -2147,36 +2121,11 @@
               // No point in trying to catch a typeinfo that was already caught.
               if (!AlreadyCaught.insert(TypeInfo))
                 continue;
-              Args.push_back(TypeInfo);
-              AllCaught = TypeInfo == CatchAll;
-              if (AllCaught)
-                break;
+              LPadInst->addClause(TypeInfo);
             }
           }
         break;
       }
-
-    if (HasCleanup) {
-      if (Args.size() == 2)
-        // Insert a sentinel indicating that this is a cleanup-only selector.
-        Args.push_back(Builder.getInt32(0));
-      else if (!AllCaught)
-        // Some exceptions from this region may not be caught by any handler.
-        // Since invokes are required to branch to the unwind label no matter
-        // what exception is being unwound, append a catch-all.  I have a plan
-        // that will make all such horrible hacks unnecessary, but unfortunately
-        // this comment is too short to explain it.
-        Args.push_back(CatchAll);
-    }
-
-    // Emit the selector call.
-    Value *Filter = Builder.CreateCall(SlctrIntr, Args, "filter");
-
-    // Store it if made use of elsewhere.
-    if (RegionNo < ExceptionFilters.size() && ExceptionFilters[RegionNo])
-      Builder.CreateStore(Filter, ExceptionFilters[RegionNo]);
-
-    Args.clear();
   }
 
   NormalInvokes.clear();
@@ -2226,23 +2175,17 @@
     if (LandingPad) {
       BeginBlock(LandingPad);
 
-      // Generate an empty (i.e. catch-all) filter in the landing pad.
-      Function *ExcIntr = Intrinsic::getDeclaration(TheModule,
-                                                    Intrinsic::eh_exception);
-      Function *SlctrIntr = Intrinsic::getDeclaration(TheModule,
-                                                      Intrinsic::eh_selector);
-      Value *Args[3];
-      // The exception pointer.
-      Args[0] = Builder.CreateCall(ExcIntr, "exc_ptr");
-      // The personality function.
+      // Generate a landingpad instruction with an empty (i.e. catch-all) filter
+      // clause.
+      Type *UnwindDataTy = StructType::get(Builder.getInt8PtrTy(),
+                                           Builder.getInt32Ty(), NULL);
       tree personality = DECL_FUNCTION_PERSONALITY(FnDecl);
       assert(personality && "No-throw region but no personality function!");
-      Args[1] = Builder.CreateBitCast(DECL_LLVM(personality),
-                                      Type::getInt8PtrTy(Context));
-      // One more than the filter length.
-      Args[2] = Builder.getInt32(1);
-      // Create the selector call.
-      Builder.CreateCall(SlctrIntr, Args, "filter");
+      LandingPadInst *LPadInst =
+        Builder.CreateLandingPad(UnwindDataTy, DECL_LLVM(personality), 1,
+                                 "exc");
+      ArrayType *FilterTy = ArrayType::get(Builder.getInt8PtrTy(), 0);
+      LPadInst->addClause(ConstantArray::get(FilterTy, ArrayRef<Constant*>()));
 
       if (LandingPad != FailureBlock) {
         // Make sure all invokes unwind to the new landing pad.
@@ -2279,34 +2222,6 @@
   }
 }
 
-/// EmitRewindBlock - Emit the block containing code to continue unwinding an
-/// exception.
-void TreeToLLVM::EmitRewindBlock() {
-  if (!RewindBB)
-    return;
-
-  BeginBlock (RewindBB);
-
-  // The exception pointer to continue unwinding.
-  assert(RewindTmp && "Rewind block but nothing to unwind?");
-  Value *ExcPtr = Builder.CreateLoad(RewindTmp);
-
-  // Generate an explicit call to _Unwind_Resume_or_Rethrow.
-  // FIXME: On ARM this should be a call to __cxa_end_cleanup with no arguments.
-  std::vector<Type*> Params(1, Type::getInt8PtrTy(Context));
-  FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Params,
-                                        false);
-  Constant *RewindFn =
-    TheModule->getOrInsertFunction("_Unwind_Resume_or_Rethrow", FTy);
-
-  // Pass it to _Unwind_Resume_or_Rethrow.
-  CallInst *Rewind = Builder.CreateCall(RewindFn, ExcPtr);
-
-  // This call does not return.
-  Rewind->setDoesNotReturn();
-  Builder.CreateUnreachable();
-}
-
 
 //===----------------------------------------------------------------------===//
 //                           ... Expressions ...
@@ -8135,7 +8050,7 @@
         if (!AlreadyCaught.insert(TypeInfo))
           continue;
 
-        TypeInfo = Builder.CreateBitCast(TypeInfo, Type::getInt8PtrTy(Context));
+        TypeInfo = Builder.CreateBitCast(TypeInfo, Builder.getInt8PtrTy());
 
         // Call get eh type id.
         Value *TypeID = Builder.CreateCall(TypeIDIntr, TypeInfo, "typeid");
@@ -8220,18 +8135,15 @@
     return;
   }
 
-  // The exception unwinds out of the function.  Note the exception to unwind.
-  if (!RewindTmp) {
-    RewindTmp = CreateTemporary(Type::getInt8PtrTy(Context));
-    RewindTmp->setName("rewind_tmp");
-  }
+  // Unwind the exception out of the function using a resume instruction.
   Value *ExcPtr = Builder.CreateLoad(getExceptionPtr(src_rgn->index));
-  Builder.CreateStore(ExcPtr, RewindTmp);
-
-  // Jump to the block containing the rewind code.
-  if (!RewindBB)
-    RewindBB = BasicBlock::Create(Context, "rewind");
-  Builder.CreateBr(RewindBB);
+  Value *Filter = Builder.CreateLoad(getExceptionFilter(src_rgn->index));
+  Type *UnwindDataTy = StructType::get(Builder.getInt8PtrTy(),
+                                       Builder.getInt32Ty(), NULL);
+  Value *UnwindData = UndefValue::get(UnwindDataTy);
+  UnwindData = Builder.CreateInsertValue(UnwindData, ExcPtr, 0, "exc_ptr");
+  UnwindData = Builder.CreateInsertValue(UnwindData, Filter, 1, "filter");
+  Builder.CreateResume(UnwindData);
 }
 
 void TreeToLLVM::RenderGIMPLE_RETURN(gimple stmt) {





More information about the llvm-commits mailing list