Index: llvm/trunk/include/llvm/Analysis/LibCallSemantics.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LibCallSemantics.h +++ llvm/trunk/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 invoke instructions remaining in the current function. + inline bool isNoOpWithoutInvoke(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: llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/AsmPrinter/ARMException.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/ARMException.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -69,24 +69,32 @@ /// void ARMException::endFunction(const MachineFunction *MF) { ARMTargetStreamer &ATS = getTargetStreamer(); + const Function *F = MF->getFunction(); + const Function *Per = nullptr; + if (F->hasPersonalityFn()) + Per = dyn_cast(F->getPersonalityFn()->stripPointerCasts()); + assert(!MMI->getPersonality() || Per == MMI->getPersonality()); + bool forceEmitPersonality = + F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && + F->needsUnwindTableEntry(); + bool shouldEmitPersonality = forceEmitPersonality || + !MMI->getLandingPads().empty(); if (!Asm->MF->getFunction()->needsUnwindTableEntry() && - MMI->getLandingPads().empty()) + !shouldEmitPersonality) ATS.emitCantUnwind(); - else { - if (!MMI->getLandingPads().empty()) { - // Emit references to personality. - if (const Function *Personality = MMI->getPersonality()) { - MCSymbol *PerSym = Asm->getSymbol(Personality); - Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global); - ATS.emitPersonality(PerSym); - } + else if (shouldEmitPersonality) { + // Emit references to personality. + if (Per) { + MCSymbol *PerSym = Asm->getSymbol(Per); + Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global); + ATS.emitPersonality(PerSym); + } - // Emit .handlerdata directive. - ATS.emitHandlerData(); + // Emit .handlerdata directive. + ATS.emitHandlerData(); - // Emit actual exception table - emitExceptionTable(); - } + // Emit actual exception table + emitExceptionTable(); } if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -89,6 +89,7 @@ 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(); @@ -104,10 +105,24 @@ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); unsigned PerEncoding = TLOF.getPersonalityEncoding(); - const Function *Per = MMI->getPersonality(); - - shouldEmitPersonality = hasLandingPads && - PerEncoding != dwarf::DW_EH_PE_omit && Per; + const Function *Per = nullptr; + if (F->hasPersonalityFn()) + Per = dyn_cast(F->getPersonalityFn()->stripPointerCasts()); + assert(!MMI->getPersonality() || Per == MMI->getPersonality()); + + // 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 invokes + !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && + // ... and we're not explicitly asked not to emit it + F->needsUnwindTableEntry(); + + shouldEmitPersonality = + (forceEmitPersonality || + (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && + Per; unsigned LSDAEncoding = TLOF.getLSDAEncoding(); shouldEmitLSDA = shouldEmitPersonality && @@ -123,6 +138,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: llvm/trunk/lib/CodeGen/AsmPrinter/EHStreamer.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp @@ -74,8 +74,12 @@ if (F->hasPersonalityFn()) Per = dyn_cast(F->getPersonalityFn()->stripPointerCasts()); - shouldEmitPersonality = hasLandingPads && - PerEncoding != dwarf::DW_EH_PE_omit && Per; + bool forceEmitPersonality = + F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && + F->needsUnwindTableEntry(); + + shouldEmitPersonality = forceEmitPersonality || (hasLandingPads && + PerEncoding != dwarf::DW_EH_PE_omit && Per); unsigned LSDAEncoding = TLOF.getLSDAEncoding(); shouldEmitLSDA = shouldEmitPersonality && Index: llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineModuleInfo.cpp +++ llvm/trunk/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: llvm/trunk/test/CodeGen/X86/eh-nolandingpads.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/eh-nolandingpads.ll +++ llvm/trunk/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 +}