[WinEH] Fix xdata generation when no catch object is present
authorReid Kleckner <reid@kleckner.net>
Tue, 7 Apr 2015 19:46:38 +0000 (19:46 +0000)
committerReid Kleckner <reid@kleckner.net>
Tue, 7 Apr 2015 19:46:38 +0000 (19:46 +0000)
The lack of a catch object is indicated by a frame escape index of -1.

Fixes PR23137.

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

include/llvm/MC/MCContext.h
lib/CodeGen/AsmPrinter/Win64Exception.cpp
test/CodeGen/WinEH/cppeh-prepared-catch-all.ll [new file with mode: 0644]

index 8ac2047b43b7dbbc1b8574256ab7e878e4c13b52..bf473ccc68eb664ce14f22eb9bf69b76e62f5a57 100644 (file)
@@ -263,7 +263,12 @@ namespace llvm {
 
     MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section);
 
+    /// Gets a symbol that will be defined to the final stack offset of a local
+    /// variable after codegen.
+    ///
+    /// @param Idx - The index of a local variable passed to @llvm.frameescape.
     MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx);
+
     MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName);
 
     /// Get the symbol for \p Name, or null.
index 3bfcaa96593dac666f3b440dcec01380c680c2e7..a685d2e23d5fbeaf0fd3b4a8a9c831eb333bd1be 100644 (file)
@@ -455,12 +455,20 @@ void Win64Exception::emitCXXFrameHandler3Table(const MachineFunction *MF) {
         const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::Create(
             ParentFrameOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
 
-        MCSymbol *FrameAllocOffset =
-            Asm->OutContext.getOrCreateFrameAllocSymbol(
-                GlobalValue::getRealLinkageName(F->getName()),
-                HT.CatchObjRecoverIdx);
-        const MCSymbolRefExpr *FrameAllocOffsetRef = MCSymbolRefExpr::Create(
-            FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
+        // Get the frame escape label with the offset of the catch object. If
+        // the index is -1, then there is no catch object, and we should emit an
+        // offset of zero, indicating that no copy will occur.
+        const MCExpr *FrameAllocOffsetRef = nullptr;
+        if (HT.CatchObjRecoverIdx >= 0) {
+          MCSymbol *FrameAllocOffset =
+              Asm->OutContext.getOrCreateFrameAllocSymbol(
+                  GlobalValue::getRealLinkageName(F->getName()),
+                  HT.CatchObjRecoverIdx);
+          FrameAllocOffsetRef = MCSymbolRefExpr::Create(
+              FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
+        } else {
+          FrameAllocOffsetRef = MCConstantExpr::Create(0, Asm->OutContext);
+        }
 
         OS.EmitIntValue(HT.Adjectives, 4);                    // Adjectives
         OS.EmitValue(createImageRel32(HT.TypeDescriptor), 4); // Type
diff --git a/test/CodeGen/WinEH/cppeh-prepared-catch-all.ll b/test/CodeGen/WinEH/cppeh-prepared-catch-all.ll
new file mode 100644 (file)
index 0000000..f395d64
--- /dev/null
@@ -0,0 +1,47 @@
+; RUN: llc < %s | FileCheck %s
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+; This test case is equivalent to:
+; extern "C" void may_throw();
+; extern "C" void test_catch_all() {
+;   try {
+;     may_throw();
+;   } catch (...) {
+;   }
+; }
+
+declare void @may_throw() #1
+declare i32 @__CxxFrameHandler3(...)
+declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #2
+declare void @llvm.eh.endcatch() #2
+
+; Function Attrs: nounwind uwtable
+define void @test_catch_all() #0 {
+entry:
+  invoke void @may_throw()
+          to label %try.cont unwind label %lpad
+
+lpad:                                             ; preds = %entry
+  %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+          catch i8* null
+  %1 = extractvalue { i8*, i32 } %0, 0
+  tail call void @llvm.eh.begincatch(i8* %1, i8* null) #2
+  tail call void @llvm.eh.endcatch() #2
+  br label %try.cont
+
+try.cont:                                         ; preds = %entry, %lpad
+  ret void
+}
+
+; CHECK-LABEL: $handlerMap$0$test_catch_all:
+; CHECK:         .long   {{[0-9]+}}
+; CHECK:         .long   0
+; CHECK:         .long   0
+; CHECK:         .long   test_catch_all.catch@IMGREL
+; CHECK:         .long   .Ltest_catch_all.catch$parent_frame_offset
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }