Index: include/llvm/CodeGen/AsmPrinter.h =================================================================== --- include/llvm/CodeGen/AsmPrinter.h +++ include/llvm/CodeGen/AsmPrinter.h @@ -168,9 +168,6 @@ /// If the target supports dwarf debug info, this pointer is non-null. DwarfDebug *DD = nullptr; - /// If the current module uses dwarf CFI annotations strictly for debugging. - bool isCFIMoveForDebugging = false; - protected: explicit AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer); @@ -302,7 +299,7 @@ /// Returns false if needsCFIMoves() == CFI_M_EH for any function /// in the module. - bool needsOnlyDebugCFIMoves() const { return isCFIMoveForDebugging; } + bool needsOnlyDebugCFIMoves() const; bool needsSEHMoves(); Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -309,28 +309,6 @@ } } - switch (MAI->getExceptionHandlingType()) { - case ExceptionHandling::SjLj: - case ExceptionHandling::DwarfCFI: - case ExceptionHandling::ARM: - isCFIMoveForDebugging = true; - if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI) - break; - for (auto &F: M.getFunctionList()) { - // If the module contains any function with unwind data, - // .eh_frame has to be emitted. - // Ignore functions that won't get emitted. - if (!F.isDeclarationForLinker() && F.needsUnwindTableEntry()) { - isCFIMoveForDebugging = false; - break; - } - } - break; - default: - isCFIMoveForDebugging = false; - break; - } - EHStreamer *ES = nullptr; switch (MAI->getExceptionHandlingType()) { case ExceptionHandling::None: @@ -370,6 +348,30 @@ return false; } +bool AsmPrinter::needsOnlyDebugCFIMoves() const { + switch (MAI->getExceptionHandlingType()) { + case ExceptionHandling::SjLj: + case ExceptionHandling::DwarfCFI: + case ExceptionHandling::ARM: + if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI) + return true; + for (auto &F: MMI->getModule()->getFunctionList()) { + // If the module contains any function with unwind data, + // .eh_frame has to be emitted. + // Ignore functions that won't get emitted. + MachineFunction *MF = MMI->getMachineFunction(F); + bool hasLandingPads = MF && !MF->getLandingPads().empty(); + if (!F.isDeclarationForLinker() && + (F.needsUnwindTableEntry() || hasLandingPads)) { + return false; + } + } + return true; + default: + return false; + } +} + static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) { if (!MAI.hasWeakDefCanBeHiddenDirective()) return false; @@ -913,7 +915,8 @@ AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() const { if (MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI && - MF->getFunction().needsUnwindTableEntry()) + (MF->getFunction().needsUnwindTableEntry() || + !MF->getLandingPads().empty())) return CFI_M_EH; if (MMI->hasDebugInfo()) Index: test/CodeGen/X86/eh_frame_nounwind.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/eh_frame_nounwind.ll @@ -0,0 +1,107 @@ +; RUN: llc -mtriple=i386 < %s -filetype=obj | llvm-dwarfdump -eh-frame - | FileCheck %s + +; Test that .eh_frame contents are generated for nounwind functions +; with landingpads. + +; CHECK: .eh_frame contents: +; CHECK: {{.*}}CIE{{.*}} +; CHECK: {{.*}}FDE{{.*}} + +target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" +target triple = "i386" + +$__clang_call_terminate = comdat any + +@_ZTIi = external constant i8* + +; Function Attrs: noinline nounwind optnone +define dso_local i32 @_Z3foov() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +entry: + %retval = alloca i32, align 4 + %exn.slot = alloca i8* + %ehselector.slot = alloca i32 + %x = alloca i32, align 4 + %exception = call i8* @__cxa_allocate_exception(i32 4) #3 + %0 = bitcast i8* %exception to i32* + store i32 1, i32* %0, align 16 + invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #4 + to label %unreachable unwind label %lpad + +lpad: ; preds = %entry + %1 = landingpad { i8*, i32 } + catch i8* bitcast (i8** @_ZTIi to i8*) + catch i8* null + %2 = extractvalue { i8*, i32 } %1, 0 + store i8* %2, i8** %exn.slot, align 4 + %3 = extractvalue { i8*, i32 } %1, 1 + store i32 %3, i32* %ehselector.slot, align 4 + br label %catch.dispatch + +catch.dispatch: ; preds = %lpad + %sel = load i32, i32* %ehselector.slot, align 4 + %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #3 + %matches = icmp eq i32 %sel, %4 + br i1 %matches, label %catch, label %terminate.handler + +catch: ; preds = %catch.dispatch + %exn = load i8*, i8** %exn.slot, align 4 + %5 = call i8* @__cxa_begin_catch(i8* %exn) #3 + %6 = bitcast i8* %5 to i32* + %7 = load i32, i32* %6, align 4 + store i32 %7, i32* %x, align 4 + store i32 0, i32* %retval, align 4 + call void @__cxa_end_catch() #3 + br label %return + +try.cont: ; No predecessors! + store i32 1, i32* %retval, align 4 + br label %return + +return: ; preds = %try.cont, %catch + %8 = load i32, i32* %retval, align 4 + ret i32 %8 + +terminate.handler: ; preds = %catch.dispatch + %exn1 = load i8*, i8** %exn.slot, align 4 + call void @__clang_call_terminate(i8* %exn1) #5 + unreachable + +unreachable: ; preds = %entry + unreachable +} + +declare i8* @__cxa_allocate_exception(i32) + +declare void @__cxa_throw(i8*, i8*, i8*) + +declare i32 @__gxx_personality_v0(...) + +; Function Attrs: nounwind readnone +declare i32 @llvm.eh.typeid.for(i8*) #1 + +; Function Attrs: noinline noreturn nounwind +define linkonce_odr hidden void @__clang_call_terminate(i8*) #2 comdat { + %2 = call i8* @__cxa_begin_catch(i8* %0) #3 + call void @_ZSt9terminatev() #5 + unreachable +} + +declare i8* @__cxa_begin_catch(i8*) + +declare void @_ZSt9terminatev() + +declare void @__cxa_end_catch() + +attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone } +attributes #2 = { noinline noreturn nounwind } +attributes #3 = { nounwind } +attributes #4 = { noreturn } +attributes #5 = { noreturn nounwind } + +!llvm.module.flags = !{!0, !1} +!llvm.ident = !{!2} + +!0 = !{i32 1, !"NumRegisterParameters", i32 0} +!1 = !{i32 1, !"wchar_size", i32 4} +!2 = !{!"clang version 7.0.0 (https://github.com/llvm-mirror/clang.git 43eac1f9d7d2c985831b485d9ccc807416d1cf29) (https://github.com/llvm-mirror/llvm.git eac9f2c06322ac1db665f3bc432b2b4fdcc81eed)"}