[llvm-commits] [llvm-gcc-4.2] r45471 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h

Duncan Sands baldrick at free.fr
Mon Dec 31 06:05:53 PST 2007


Author: baldrick
Date: Mon Dec 31 08:05:52 2007
New Revision: 45471

URL: http://llvm.org/viewvc/llvm-project?rev=45471&view=rev
Log:
Due to gcc inlining, it is possible for resx
expressions (i.e. rethrows) to occur inside
must-not-throw regions.  This is illegal, and
can be handled by either executing the code
specified by lang_protect_cleanup_actions
(since this code should already have been emitted
into some basic block, this means locating that
basic block and jumping to it), or by marking
the call with the nounwind attribute.  Because
using the nounwind attribute seems to be both
simpler and more robust, that is the solution
implemented here.  This fixes the last known eh
problem on x86 linux with llvm-gcc-4.2.

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-internal.h

Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=45471&r1=45470&r2=45471&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Mon Dec 31 08:05:52 2007
@@ -349,7 +349,7 @@
 TreeToLLVM::TreeToLLVM(tree fndecl) : TD(getTargetData()) {
   FnDecl = fndecl;
   Fn = 0;
-  ReturnBB = UnwindBB = 0;
+  ReturnBB = UnwindBB = NoUnwindBB = 0;
   
   if (TheDebugInfo) {
     expanded_location Location = expand_location(DECL_SOURCE_LOCATION (fndecl));
@@ -755,6 +755,7 @@
   EmitLandingPads();
   EmitPostPads();
   EmitUnwindBlock();
+  EmitNoUnwindBlock();
 
   // If this function takes the address of a label, emit the indirect goto
   // block.
@@ -1863,7 +1864,7 @@
                                  PointerType::getUnqual(Type::Int8Ty)));
 
     // Add selections for each handler.
-    foreach_reachable_handler (i, false, AddHandler, &Handlers);
+    foreach_reachable_handler(i, false, AddHandler, &Handlers);
 
     for (std::vector<struct eh_region *>::iterator I = Handlers.begin(),
          E = Handlers.end(); I != E; ++I) {
@@ -2023,7 +2024,7 @@
     }
 
     // Emit a RESX_EXPR which skips handlers with no post landing pad.
-    foreach_reachable_handler (i, true, AddHandler, &Handlers);
+    foreach_reachable_handler(i, true, AddHandler, &Handlers);
 
     BasicBlock *TargetBB = NULL;
 
@@ -2038,13 +2039,20 @@
         break;
     }
 
-    if (!TargetBB) {
+    if (TargetBB) {
+      Builder.CreateBr(TargetBB);
+    } else if (can_throw_external_1(i, true)) {
+      // Unwinding continues in the caller.
       if (!UnwindBB)
         UnwindBB = new BasicBlock("Unwind");
-      TargetBB = UnwindBB;
+      Builder.CreateBr(UnwindBB);
+    } else {
+      // Unwinding in a must_not_throw region - notify the runtime.
+      if (!NoUnwindBB)
+        NoUnwindBB = new BasicBlock("NoUnwind");
+      Builder.CreateBr(NoUnwindBB);
     }
 
-    Builder.CreateBr(TargetBB);
     Handlers.clear();
   }
 }
@@ -2062,6 +2070,22 @@
   }
 }
 
+/// EmitNoUnwindBlock - Emit the lazily created EH illegal-unwind block.
+void TreeToLLVM::EmitNoUnwindBlock() {
+  if (NoUnwindBB) {
+    CreateExceptionValues();
+    EmitBlock(NoUnwindBB);
+    // Fetch and store exception handler.
+    Value *Arg = Builder.CreateLoad(ExceptionValue, "eh_ptr");
+    assert(llvm_unwind_resume_libfunc && "no unwind resume function!");
+    CallInst *Call =
+      Builder.CreateCall(DECL_LLVM(llvm_unwind_resume_libfunc), Arg);
+    // Illegal unwind - notify the runtime.
+    Call->setDoesNotThrow();
+    Builder.CreateUnreachable();
+  }
+}
+
 //===----------------------------------------------------------------------===//
 //                           ... Expressions ...
 //===----------------------------------------------------------------------===//
@@ -3267,7 +3291,7 @@
   unsigned RegionNo = TREE_INT_CST_LOW(TREE_OPERAND (exp, 0));
   std::vector<struct eh_region *> Handlers;
 
-  foreach_reachable_handler (RegionNo, true, AddHandler, &Handlers);
+  foreach_reachable_handler(RegionNo, true, AddHandler, &Handlers);
 
   if (!Handlers.empty()) {
     for (std::vector<struct eh_region *>::iterator I = Handlers.begin(),
@@ -3276,10 +3300,16 @@
       getPostPad(get_eh_region_number(*I));
 
     Builder.CreateBr(getPostPad(get_eh_region_number(*Handlers.begin())));
-  } else {
+  } else if (can_throw_external_1(RegionNo, true)) {
+    // Unwinding continues in the caller.
     if (!UnwindBB)
       UnwindBB = new BasicBlock("Unwind");
     Builder.CreateBr(UnwindBB);
+  } else {
+    // Unwinding in a must_not_throw region - notify the runtime.
+    if (!NoUnwindBB)
+      NoUnwindBB = new BasicBlock("NoUnwind");
+    Builder.CreateBr(NoUnwindBB);
   }
 
   EmitBlock(new BasicBlock(""));

Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=45471&r1=45470&r2=45471&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Mon Dec 31 08:05:52 2007
@@ -267,7 +267,8 @@
   Function *Fn;
   BasicBlock *ReturnBB;
   BasicBlock *UnwindBB;
-  
+  BasicBlock *NoUnwindBB;
+
   // State that changes as the function is emitted.
 
   /// Builder - Instruction creator, the location to insert into is always the
@@ -421,6 +422,9 @@
   /// EmitUnwindBlock - Emit the lazily created EH unwind block.
   void EmitUnwindBlock();
 
+  /// EmitNoUnwindBlock - Emit the lazily created EH illegal-unwind block.
+  void EmitNoUnwindBlock();
+
 private: // Helpers for exception handling.
 
   /// CreateExceptionValues - Create values used internally by exception





More information about the llvm-commits mailing list