diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -192,6 +192,9 @@ void *DiagContext; }; + // Flags representing what CFI move sections are required for a function. + enum CFIMoveType : unsigned { CFI_M_None = 0, CFI_M_EH = 1, CFI_M_Debug = 2 }; + private: /// If generated on the fly this own the instance. std::unique_ptr OwnedMDT; @@ -206,8 +209,8 @@ /// 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; + /// Cached bitwise OR of CFIMoveType flags for all functions in the module. + unsigned ModuleCFIMoveTypes = CFI_M_None; protected: explicit AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer); @@ -362,12 +365,12 @@ void emitRemarksSection(remarks::RemarkStreamer &RS); - enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; - CFIMoveType needsCFIMoves() const; - - /// Returns false if needsCFIMoves() == CFI_M_EH for any function - /// in the module. - bool needsOnlyDebugCFIMoves() const { return isCFIMoveForDebugging; } + /// Get the CFIMoveType flags for a function. + unsigned getCFIMoveTypes(const Function &F) const; + /// Get the CFIMoveType flags for a function. + unsigned getCFIMoveTypes(const MachineFunction &MF) const; + /// Get the bitwise OR of CFIMoveType flags for all functions in the module. + unsigned getCFIMoveTypes() const { return ModuleCFIMoveTypes; } bool needsSEHMoves(); diff --git a/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp b/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp --- a/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -39,14 +39,13 @@ if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) getTargetStreamer().emitFnStart(); // See if we need call frame info. - AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); - assert(MoveType != AsmPrinter::CFI_M_EH && + unsigned MoveTypes = Asm->getCFIMoveTypes(*MF); + assert(!(MoveTypes & AsmPrinter::CFI_M_EH) && "non-EH CFI not yet supported in prologue with EHABI lowering"); - if (MoveType == AsmPrinter::CFI_M_Debug) { + if (MoveTypes & AsmPrinter::CFI_M_Debug) { if (!hasEmittedCFISections) { - if (Asm->needsOnlyDebugCFIMoves()) - Asm->OutStreamer->emitCFISections(false, true); + Asm->OutStreamer->emitCFISections(false, true); hasEmittedCFISections = true; } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -325,21 +325,12 @@ 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; - } - } + for (auto &F : M.getFunctionList()) + ModuleCFIMoveTypes |= getCFIMoveTypes(F); + assert(MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI || + !(ModuleCFIMoveTypes & CFI_M_EH)); break; default: - isCFIMoveForDebugging = false; break; } @@ -980,15 +971,28 @@ return true; } -AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() const { +unsigned AsmPrinter::getCFIMoveTypes(const Function &F) const { + // Ignore functions that won't get emitted. + if (F.isDeclarationForLinker()) + return CFI_M_None; + + unsigned Type = CFI_M_None; + if (MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI && - MF->getFunction().needsUnwindTableEntry()) - return CFI_M_EH; + F.needsUnwindTableEntry()) { + Type |= CFI_M_EH; + } else if (MMI->hasDebugInfo()) { + Type |= CFI_M_Debug; + } - if (MMI->hasDebugInfo() || MF->getTarget().Options.ForceDwarfFrameSection) - return CFI_M_Debug; + if (TM.Options.ForceDwarfFrameSection) + Type |= CFI_M_Debug; + + return Type; +} - return CFI_M_None; +unsigned AsmPrinter::getCFIMoveTypes(const MachineFunction &MF) const { + return getCFIMoveTypes(MF.getFunction()); } bool AsmPrinter::needsSEHMoves() { @@ -1001,7 +1005,7 @@ ExceptionHandlingType != ExceptionHandling::ARM) return; - if (needsCFIMoves() == CFI_M_None) + if (getCFIMoveTypes(*MF) == CFI_M_None) return; // If there is no "real" instruction following this CFI instruction, skip diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -94,9 +94,7 @@ bool hasLandingPads = !MF->getLandingPads().empty(); // See if we need frame move info. - AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); - - shouldEmitMoves = MoveType != AsmPrinter::CFI_M_None; + shouldEmitMoves = Asm->getCFIMoveTypes(*MF) != AsmPrinter::CFI_M_None; const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); unsigned PerEncoding = TLOF.getPersonalityEncoding(); @@ -133,10 +131,12 @@ return; if (!hasEmittedCFISections) { - if (Asm->needsOnlyDebugCFIMoves()) - Asm->OutStreamer->emitCFISections(false, true); - else if (Asm->TM.Options.ForceDwarfFrameSection) - Asm->OutStreamer->emitCFISections(true, true); + unsigned MoveTypes = Asm->getCFIMoveTypes(); + // If we don't say anything it implies `.cfi_sections .eh_frame`, so we + // chose not to be verbose in that case. + if (MoveTypes & AsmPrinter::CFI_M_Debug) + Asm->OutStreamer->emitCFISections(MoveTypes & AsmPrinter::CFI_M_EH, + MoveTypes & AsmPrinter::CFI_M_Debug); hasEmittedCFISections = true; } diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -1198,7 +1198,7 @@ ExceptionHandlingType != ExceptionHandling::ARM) return; - if (needsCFIMoves() == CFI_M_None) + if (getCFIMoveTypes(*MF) == CFI_M_None) return; OutStreamer->emitCFIBKeyFrame();