[PATCH 1/2] Always create unwind table entries for functions marked `uwtable`
Björn Steinbrink
bsteinbr at gmail.com
Sun Feb 16 11:13:31 PST 2014
As explained in Attributes.h, functions marked `uwtable` should always
have an entry in the unwind table, even if they are additionally marked
`nounwind`.
But the check in codegen only checks if the function is marked
`nounwind` and if so, it always omits the table entry, which is wrong.
The Function class already provides a method to correctly check if a
table entry is required. Using that instead of the `nounwind` check
fixes problem.
---
lib/CodeGen/AsmPrinter/DwarfException.cpp | 40 +++++++++--------
lib/CodeGen/AsmPrinter/DwarfException.h | 6 +--
test/CodeGen/X86/gcc_except_table.ll | 73 +++++++++++++++++++++++++++++--
3 files changed, 93 insertions(+), 26 deletions(-)
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index f72bc81..4ff5599 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -181,12 +181,12 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
return SizeActions;
}
-/// CallToNoUnwindFunction - Return `true' if this is a call to a function
-/// marked `nounwind'. Return `false' otherwise.
-bool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) {
+ /// CallNeedsUnwindTableEntry - Return `true' if this is a call to a function
+ /// that needs an unwind table entry. Return `false' otherwise.
+bool DwarfException::CallNeedsUnwindTableEntry(const MachineInstr *MI) {
assert(MI->isCall() && "This should be a call instruction!");
- bool MarkedNoUnwind = false;
+ bool NeedsUnwindTableEntry = true;
bool SawFunc = false;
for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
@@ -204,15 +204,15 @@ bool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) {
//
// FIXME: Determine if there's a way to say that `F' is the callee or
// parameter.
- MarkedNoUnwind = false;
+ NeedsUnwindTableEntry = true;
break;
}
- MarkedNoUnwind = F->doesNotThrow();
+ NeedsUnwindTableEntry = F->needsUnwindTableEntry();
SawFunc = true;
}
- return MarkedNoUnwind;
+ return NeedsUnwindTableEntry;
}
/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke
@@ -230,9 +230,11 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
// The end label of the previous invoke or nounwind try-range.
MCSymbol *LastLabel = 0;
- // Whether there is a potentially throwing instruction (currently this means
- // an ordinary call) between the end of the previous try-range and now.
- bool SawPotentiallyThrowing = false;
+ // Whether there is an instruction that forces us to emit unwind table
+ // entries for calls between the end of the previous try-range and now.
+ // Currently this means function calls that potentially throw or are marked
+ // to always required an unwind table entry.
+ bool ForceCallSiteEntry = false;
// Whether the last CallSite entry was for an invoke.
bool PreviousIsInvoke = false;
@@ -244,14 +246,14 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
MI != E; ++MI) {
if (!MI->isLabel()) {
if (MI->isCall())
- SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI);
+ ForceCallSiteEntry |= CallNeedsUnwindTableEntry(MI);
continue;
}
// End of the previous try-range?
MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol();
if (BeginLabel == LastLabel)
- SawPotentiallyThrowing = false;
+ ForceCallSiteEntry = false;
// Beginning of a new try-range?
RangeMapType::const_iterator L = PadMap.find(BeginLabel);
@@ -265,10 +267,10 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
"Inconsistent landing pad map!");
// For Dwarf exception handling (SjLj handling doesn't use this). If some
- // instruction between the previous try-range and this one may throw,
- // create a call-site entry with no landing pad for the region between the
- // try-ranges.
- if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) {
+ // instruction between the previous try-range and this one requires an
+ // unwind table entry create a call-site entry with no landing pad for
+ // the region between the try-ranges.
+ if (ForceCallSiteEntry && Asm->MAI->isExceptionHandlingDwarf()) {
CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 };
CallSites.push_back(Site);
PreviousIsInvoke = false;
@@ -316,9 +318,9 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
}
// 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 && Asm->MAI->isExceptionHandlingDwarf()) {
+ // function requires an unwind table entry, create a call-site entry with no
+ // landing pad for the region following the try-range.
+ if (ForceCallSiteEntry && Asm->MAI->isExceptionHandlingDwarf()) {
CallSiteEntry Site = { LastLabel, 0, 0, 0 };
CallSites.push_back(Site);
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h
index a28eaf0..ba02f70 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.h
+++ b/lib/CodeGen/AsmPrinter/DwarfException.h
@@ -85,9 +85,9 @@ protected:
SmallVectorImpl<ActionEntry> &Actions,
SmallVectorImpl<unsigned> &FirstActions);
- /// CallToNoUnwindFunction - Return `true' if this is a call to a function
- /// marked `nounwind'. Return `false' otherwise.
- bool CallToNoUnwindFunction(const MachineInstr *MI);
+ /// CallNeedsUnwindTableEntry - Return `true' if this is a call to a function
+ /// that needs an unwind table entry. Return `false' otherwise.
+ bool CallNeedsUnwindTableEntry(const MachineInstr *MI);
/// ComputeCallSiteTable - Compute the call-site table. The entry for an
/// invoke has a try-range containing the call, a non-zero landing pad and an
diff --git a/test/CodeGen/X86/gcc_except_table.ll b/test/CodeGen/X86/gcc_except_table.ll
index fcc4e9f..b1b8490 100644
--- a/test/CodeGen/X86/gcc_except_table.ll
+++ b/test/CodeGen/X86/gcc_except_table.ll
@@ -24,10 +24,75 @@ eh.resume:
resume { i8*, i32 } %0
}
-declare void @_Z1fv() optsize
-
-declare i32 @__gxx_personality_v0(...)
-
; CHECK: Leh_func_end0:
; CHECK: GCC_except_table0
; CHECK: = Leh_func_end0-
+
+define void @test_uwtable() uwtable {
+ call void @uwtable()
+ invoke void @_Z1fv() to label %ret unwind label %unwind
+
+ret:
+ ret void
+
+unwind:
+ %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
+ resume { i8*, i32 } %1
+}
+
+; CHECK: GCC_except_table1
+; CHECK: Call Site 1
+; CHECK: has no landing pad
+; CHECK: Call Site 2
+; CHECK: jumps to
+; CHECK: Call Site 3
+; CHECK: has no landing pad
+
+define void @test_nounwind() uwtable {
+ call void @nounwind()
+ invoke void @_Z1fv() to label %ret unwind label %unwind
+
+ret:
+ ret void
+
+unwind:
+ %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
+ resume { i8*, i32 } %1
+}
+
+; CHECK: GCC_except_table2
+; CHECK: Call Site 1
+; CHECK: jumps to
+; CHECK: Call Site 2
+; CHECK: has no landing pad
+
+define void @test_both() uwtable {
+ call void @both()
+ invoke void @_Z1fv() to label %ret unwind label %unwind
+
+ret:
+ ret void
+
+unwind:
+ %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
+ resume { i8*, i32 } %1
+}
+
+; CHECK: GCC_except_table3
+; CHECK: Call Site 1
+; CHECK: has no landing pad
+; CHECK: Call Site 2
+; CHECK: jumps to
+; CHECK: Call Site 3
+; CHECK: has no landing pad
+
+declare void @uwtable() uwtable;
+declare void @nounwind() nounwind;
+declare void @both() uwtable nounwind;
+
+declare void @_Z1fv() optsize
+
+declare i32 @__gxx_personality_v0(...)
--
1.9.0.rc3
More information about the llvm-commits
mailing list