diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 8ac2047b43b..bf473ccc68e 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -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. diff --git a/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/lib/CodeGen/AsmPrinter/Win64Exception.cpp index 3bfcaa96593..a685d2e23d5 100644 --- a/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -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 index 00000000000..f395d64c7b5 --- /dev/null +++ b/test/CodeGen/WinEH/cppeh-prepared-catch-all.ll @@ -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 }