Index: include/llvm/Analysis/LibCallSemantics.h =================================================================== --- include/llvm/Analysis/LibCallSemantics.h +++ include/llvm/Analysis/LibCallSemantics.h @@ -206,6 +206,18 @@ llvm_unreachable("invalid enum"); } + /// \brief Return true if this personality may be safely removed if there + /// are no landing pads in the current function. + inline bool isNoOpWithoutLpad(EHPersonality Pers) { + switch (Pers) { + case EHPersonality::Unknown: + return false; + // All known personalities currently have this behavior + default: return true; + } + llvm_unreachable("invalid enum"); + } + bool canSimplifyInvokeNoUnwind(const Function *F); } // end namespace llvm Index: include/llvm/CodeGen/MachineModuleInfo.h =================================================================== --- include/llvm/CodeGen/MachineModuleInfo.h +++ include/llvm/CodeGen/MachineModuleInfo.h @@ -320,6 +320,7 @@ /// information. void addPersonality(MachineBasicBlock *LandingPad, const Function *Personality); + void addPersonality(const Function *Personality); void addWinEHState(MachineBasicBlock *LandingPad, int State); Index: lib/CodeGen/AsmPrinter/DwarfCFIException.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -89,10 +89,21 @@ void DwarfCFIException::beginFunction(const MachineFunction *MF) { shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; + const Function *F = MF->getFunction(); // If any landing pads survive, we need an EH table. bool hasLandingPads = !MMI->getLandingPads().empty(); + // Emit a personality function even when there are no landing pads + bool forceEmitPersonality = + // ...if a personality function is explicitly specified + F->hasPersonalityFn() && + // ... and it's not known to be a noop in the absence of landing pads + !isNoOpWithoutLpad(classifyEHPersonality(F->getPersonalityFn())) && + // ... and we're no explicitly asked not to emit it + (!F->hasFnAttribute(Attribute::NoUnwind) || + F->hasFnAttribute(Attribute::UWTable)); + // See if we need frame move info. AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); if (MoveType == AsmPrinter::CFI_M_EH || @@ -104,10 +115,16 @@ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); unsigned PerEncoding = TLOF.getPersonalityEncoding(); - const Function *Per = MMI->getPersonality(); + const Function *Per = F->hasPersonalityFn() + ? dyn_cast<Function>(F->getPersonalityFn()) + : nullptr; + if (!Per) + Per = MMI->getPersonality(); - shouldEmitPersonality = hasLandingPads && - PerEncoding != dwarf::DW_EH_PE_omit && Per; + shouldEmitPersonality = + (forceEmitPersonality || + (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && + Per; unsigned LSDAEncoding = TLOF.getLSDAEncoding(); shouldEmitLSDA = shouldEmitPersonality && @@ -123,6 +140,11 @@ if (!shouldEmitPersonality) return; + // If we are forced to emit this personality, make sure to record + // it because it might not appear in any landingpad + if (forceEmitPersonality) + MMI->addPersonality(Per); + const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI); Asm->OutStreamer->EmitCFIPersonality(Sym, PerEncoding); Index: lib/CodeGen/AsmPrinter/EHStreamer.cpp =================================================================== --- lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -309,7 +309,7 @@ // If some instruction between the previous try-range and the end of the // function may throw, create a call-site entry with no landing pad for the // region following the try-range. - if (SawPotentiallyThrowing && !IsSJLJ) { + if (SawPotentiallyThrowing && !IsSJLJ && LastLabel != nullptr) { CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 }; CallSites.push_back(Site); } Index: lib/CodeGen/MachineModuleInfo.cpp =================================================================== --- lib/CodeGen/MachineModuleInfo.cpp +++ lib/CodeGen/MachineModuleInfo.cpp @@ -320,7 +320,10 @@ const Function *Personality) { LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); LP.Personality = Personality; + addPersonality(Personality); +} +void MachineModuleInfo::addPersonality(const Function *Personality) { for (unsigned i = 0; i < Personalities.size(); ++i) if (Personalities[i] == Personality) return; Index: test/CodeGen/X86/eh-nolandingpads.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/eh-nolandingpads.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s -mtriple=x86_64-pc-linux | FileCheck %s +; Test that we emit functions with explicitly specified personality, +; even if no landing pads are left. + +declare i32 @__my_personality_v0(...) +declare void @might_throw() + +define i32 @foo() personality i32 (...)* @__my_personality_v0 { +; CHECK: .cfi_personality 3, __my_personality_v0 + call void @might_throw() + ret i32 0 +}