[CodeGen] Force emission of personality directive if explicitly specified

Summary:
Before this change, personality directives were not emitted
if there was no invoke left in the function (of course until
recently this also meant that we couldn't know what
the personality actually was). This patch forces personality directives
to still be emitted, unless it is known to be a noop in the absence of
invokes, or the user explicitly specified `nounwind` (and not
`uwtable`) on the function.

Reviewers: majnemer, rnk

Subscribers: rnk, llvm-commits

Differential Revision: http://reviews.llvm.org/D10884

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242185 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Keno Fischer
2015-07-14 19:22:51 +00:00
parent 77906b9964
commit 890c16626f
8 changed files with 81 additions and 21 deletions

View File

@@ -206,6 +206,18 @@ class InvokeInst;
llvm_unreachable("invalid enum"); 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); bool canSimplifyInvokeNoUnwind(const Function *F);
} // end namespace llvm } // end namespace llvm

View File

@@ -320,6 +320,7 @@ public:
/// information. /// information.
void addPersonality(MachineBasicBlock *LandingPad, void addPersonality(MachineBasicBlock *LandingPad,
const Function *Personality); const Function *Personality);
void addPersonality(const Function *Personality);
void addWinEHState(MachineBasicBlock *LandingPad, int State); void addWinEHState(MachineBasicBlock *LandingPad, int State);

View File

@@ -69,24 +69,32 @@ void ARMException::beginFunction(const MachineFunction *MF) {
/// ///
void ARMException::endFunction(const MachineFunction *MF) { void ARMException::endFunction(const MachineFunction *MF) {
ARMTargetStreamer &ATS = getTargetStreamer(); ARMTargetStreamer &ATS = getTargetStreamer();
const Function *F = MF->getFunction();
const Function *Per = nullptr;
if (F->hasPersonalityFn())
Per = dyn_cast<Function>(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() && if (!Asm->MF->getFunction()->needsUnwindTableEntry() &&
MMI->getLandingPads().empty()) !shouldEmitPersonality)
ATS.emitCantUnwind(); ATS.emitCantUnwind();
else { else if (shouldEmitPersonality) {
if (!MMI->getLandingPads().empty()) { // Emit references to personality.
// Emit references to personality. if (Per) {
if (const Function *Personality = MMI->getPersonality()) { MCSymbol *PerSym = Asm->getSymbol(Per);
MCSymbol *PerSym = Asm->getSymbol(Personality); Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global);
Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global); ATS.emitPersonality(PerSym);
ATS.emitPersonality(PerSym);
}
// Emit .handlerdata directive.
ATS.emitHandlerData();
// Emit actual exception table
emitExceptionTable();
} }
// Emit .handlerdata directive.
ATS.emitHandlerData();
// Emit actual exception table
emitExceptionTable();
} }
if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)

View File

@@ -89,6 +89,7 @@ void DwarfCFIException::endModule() {
void DwarfCFIException::beginFunction(const MachineFunction *MF) { void DwarfCFIException::beginFunction(const MachineFunction *MF) {
shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
const Function *F = MF->getFunction();
// If any landing pads survive, we need an EH table. // If any landing pads survive, we need an EH table.
bool hasLandingPads = !MMI->getLandingPads().empty(); bool hasLandingPads = !MMI->getLandingPads().empty();
@@ -104,10 +105,24 @@ void DwarfCFIException::beginFunction(const MachineFunction *MF) {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
unsigned PerEncoding = TLOF.getPersonalityEncoding(); unsigned PerEncoding = TLOF.getPersonalityEncoding();
const Function *Per = MMI->getPersonality(); const Function *Per = nullptr;
if (F->hasPersonalityFn())
Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
assert(!MMI->getPersonality() || Per == MMI->getPersonality());
shouldEmitPersonality = hasLandingPads && // Emit a personality function even when there are no landing pads
PerEncoding != dwarf::DW_EH_PE_omit && Per; 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(); unsigned LSDAEncoding = TLOF.getLSDAEncoding();
shouldEmitLSDA = shouldEmitPersonality && shouldEmitLSDA = shouldEmitPersonality &&
@@ -123,6 +138,11 @@ void DwarfCFIException::beginFunction(const MachineFunction *MF) {
if (!shouldEmitPersonality) if (!shouldEmitPersonality)
return; 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 = const MCSymbol *Sym =
TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI); TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
Asm->OutStreamer->EmitCFIPersonality(Sym, PerEncoding); Asm->OutStreamer->EmitCFIPersonality(Sym, PerEncoding);

View File

@@ -309,7 +309,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
// If some instruction between the previous try-range and the end of the // 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 // function may throw, create a call-site entry with no landing pad for the
// region following the try-range. // region following the try-range.
if (SawPotentiallyThrowing && !IsSJLJ) { if (SawPotentiallyThrowing && !IsSJLJ && LastLabel != nullptr) {
CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 }; CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 };
CallSites.push_back(Site); CallSites.push_back(Site);
} }

View File

@@ -74,8 +74,12 @@ void WinException::beginFunction(const MachineFunction *MF) {
if (F->hasPersonalityFn()) if (F->hasPersonalityFn())
Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts()); Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
shouldEmitPersonality = hasLandingPads && bool forceEmitPersonality =
PerEncoding != dwarf::DW_EH_PE_omit && Per; F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
F->needsUnwindTableEntry();
shouldEmitPersonality = forceEmitPersonality || (hasLandingPads &&
PerEncoding != dwarf::DW_EH_PE_omit && Per);
unsigned LSDAEncoding = TLOF.getLSDAEncoding(); unsigned LSDAEncoding = TLOF.getLSDAEncoding();
shouldEmitLSDA = shouldEmitPersonality && shouldEmitLSDA = shouldEmitPersonality &&

View File

@@ -320,7 +320,10 @@ void MachineModuleInfo::addPersonality(MachineBasicBlock *LandingPad,
const Function *Personality) { const Function *Personality) {
LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
LP.Personality = Personality; LP.Personality = Personality;
addPersonality(Personality);
}
void MachineModuleInfo::addPersonality(const Function *Personality) {
for (unsigned i = 0; i < Personalities.size(); ++i) for (unsigned i = 0; i < Personalities.size(); ++i)
if (Personalities[i] == Personality) if (Personalities[i] == Personality)
return; return;

View File

@@ -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
}