Fix ARM EHABI when function has landingpad and nounwind.
authorLogan Chien <tzuhsiang.chien@gmail.com>
Wed, 14 May 2014 16:38:30 +0000 (16:38 +0000)
committerLogan Chien <tzuhsiang.chien@gmail.com>
Wed, 14 May 2014 16:38:30 +0000 (16:38 +0000)
If the function has the landingpad instruction, then the
handlerdata should be emitted even if the function has
nouwnind attribute.  Otherwise, following code will not
work:

    void test1() noexcept {
      try {
        throw_exception();
      } catch (...) {
        log_unexpected_exception();
      }
    }

Since the cantunwind was incorrectly emitted and the
LSDA is not available.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208791 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/ARMException.cpp
test/CodeGen/ARM/ehabi-handlerdata-nounwind.ll [new file with mode: 0644]

index 97b288f19478f68310ae108e7e7a0d1dde68b937..1cb0159d10f726088cda771723accde9b345e82b 100644 (file)
@@ -59,9 +59,8 @@ void ARMException::endModule() {
 void ARMException::beginFunction(const MachineFunction *MF) {
   if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
     getTargetStreamer().emitFnStart();
-  if (Asm->MF->getFunction()->needsUnwindTableEntry())
-    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin",
-                                                  Asm->getFunctionNumber()));
+  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin",
+                                                Asm->getFunctionNumber()));
   // See if we need call frame info.
   AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves();
   assert(MoveType != AsmPrinter::CFI_M_EH &&
@@ -78,16 +77,16 @@ void ARMException::endFunction(const MachineFunction *) {
   if (shouldEmitCFI)
     Asm->OutStreamer.EmitCFIEndProc();
 
+  // Map all labels and get rid of any dead landing pads.
+  MMI->TidyLandingPads();
+
   ARMTargetStreamer &ATS = getTargetStreamer();
-  if (!Asm->MF->getFunction()->needsUnwindTableEntry())
+  if (!Asm->MF->getFunction()->needsUnwindTableEntry() &&
+      MMI->getLandingPads().empty())
     ATS.emitCantUnwind();
   else {
     Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end",
                                                   Asm->getFunctionNumber()));
-
-    // Map all labels and get rid of any dead landing pads.
-    MMI->TidyLandingPads();
-
     if (!MMI->getLandingPads().empty()) {
       // Emit references to personality.
       if (const Function * Personality =
diff --git a/test/CodeGen/ARM/ehabi-handlerdata-nounwind.ll b/test/CodeGen/ARM/ehabi-handlerdata-nounwind.ll
new file mode 100644 (file)
index 0000000..42ca988
--- /dev/null
@@ -0,0 +1,61 @@
+; Test for handlerdata when the function has landingpad and nounwind.
+
+; This test case checks whether the handlerdata is generated for the function
+; with landingpad instruction, even if the function has "nounwind" atttribute.
+;
+; For example, although the following function never throws any exception,
+; however, it is still required to generate LSDA, otherwise, we can't catch
+; the exception properly.
+;
+; void test1() noexcept {
+;   try {
+;     throw_exception();
+;   } catch (...) {
+;   }
+; }
+
+; RUN: llc -mtriple arm-unknown-linux-gnueabi -filetype=asm -o - %s \
+; RUN:   | FileCheck %s
+
+declare void @throw_exception()
+
+declare i32 @__gxx_personality_v0(...)
+
+declare i8* @__cxa_begin_catch(i8*)
+
+declare void @__cxa_end_catch()
+
+define void @test1() nounwind {
+entry:
+  invoke void @throw_exception() to label %try.cont unwind label %lpad
+
+lpad:
+  %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+          catch i8* null
+  %1 = extractvalue { i8*, i32 } %0, 0
+  %2 = tail call i8* @__cxa_begin_catch(i8* %1)
+  tail call void @__cxa_end_catch()
+  br label %try.cont
+
+try.cont:
+  ret void
+}
+
+; CHECK:   .globl test1
+; CHECK:   .align 2
+; CHECK:   .type test1,%function
+; CHECK-LABEL: test1:
+; CHECK:   .fnstart
+
+; CHECK-NOT: .cantunwind
+
+; CHECK:   .personality __gxx_personality_v0
+; CHECK:   .handlerdata
+; CHECK:   .align 2
+; CHECK-LABEL: GCC_except_table0:
+; CHECK-LABEL: .Lexception0:
+; CHECK:   .byte 255                     @ @LPStart Encoding = omit
+; CHECK:   .byte 0                       @ @TType Encoding = absptr
+; CHECK:   .asciz
+; CHECK:   .byte 3                       @ Call site Encoding = udata4
+; CHECK:   .fnend