forked from OSchip/llvm-project
SjLj based exception handling unwinding support. This patch is nasty, brutish
and short. Well, it's kinda short. Definitely nasty and brutish. The front-end generates the register/unregister calls into the SjLj runtime, call-site indices and landing pad dispatch. The back end fills in the LSDA with the call-site information provided by the front end. Catch blocks are not yet implemented. Built on Darwin and verified no llvm-core "make check" regressions. llvm-svn: 78625
This commit is contained in:
parent
4898990524
commit
693e36a3e8
|
@ -33,6 +33,8 @@
|
|||
<li><a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a></li>
|
||||
<li><a href="#llvm_eh_sjlj_setjmp"><tt>llvm.eh.sjlj.setjmp</tt></a></li>
|
||||
<li><a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a></li>
|
||||
<li><a href="#llvm_eh_sjlj_lsda"><tt>llvm.eh.sjlj.lsda</tt></a></li>
|
||||
<li><a href="#llvm_eh_sjlj_callsite"><tt>llvm.eh.sjlj.callsite</tt></a></li>
|
||||
</ol></li>
|
||||
<li><a href="#asm">Asm Table Formats</a>
|
||||
<ol>
|
||||
|
@ -414,7 +416,7 @@ a reference to a type info.</p>
|
|||
|
||||
<p>The SJLJ exception handling uses this intrinsic to force register saving
|
||||
for the current function and to store the address of the following instruction
|
||||
for use as a destination address by <a href="#llvm_eh_sjlj_setjmp">
|
||||
for use as a destination address by <a href="#llvm_eh_sjlj_longjmp">
|
||||
<tt>llvm.eh.sjlj.longjmp</tt></a>. The buffer format and the overall functioning
|
||||
of this intrinsic is compatible with the GCC <tt>__builtin_setjmp</tt>
|
||||
implementation, allowing code built with the two compilers to interoperate.</p>
|
||||
|
@ -428,6 +430,41 @@ are available for use in a target-specific manner.</p>
|
|||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="llvm_eh_sjlj_lsda">llvm.eh.sjlj.lsda</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
<pre>
|
||||
i8* %<a href="#llvm_eh_sjlj_lsda">llvm.eh.sjlj.lsda</a>( )
|
||||
</pre>
|
||||
|
||||
<p>Used for SJLJ based exception handling, the <a href="#llvm_eh_sjlj_lsda">
|
||||
<tt>llvm.eh.sjlj.lsda</tt></a> intrinsic returns the address of the Language
|
||||
Specific Data Area (LSDA) for the current function. The SJLJ front-end code
|
||||
stores this address in the exception handling function context for use by
|
||||
the runtime.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="llvm_eh_sjlj_callsite">llvm.eh.sjlj.callsite</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
<pre>
|
||||
void %<a href="#llvm_eh_sjlj_callsite">llvm.eh.sjlj.callsite</a>(i32)
|
||||
</pre>
|
||||
|
||||
<p>The SJLJ front-end allocates call site indices for invoke instrucitons.
|
||||
These values are passed to the back-end via the
|
||||
<a href="#llvm_eh_sjlj_callsite"><tt>llvm.eh.sjlj.callsite</tt></a>
|
||||
intrinsic, where they are used to build the LSDA call-site table.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_section">
|
||||
<a name="asm">Asm Table Formats</a>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H
|
||||
#define LLVM_CODEGEN_MACHINEFUNCTION_H
|
||||
|
||||
#include <map>
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/Support/DebugLoc.h"
|
||||
#include "llvm/CodeGen/Dump.h"
|
||||
|
@ -114,6 +115,15 @@ class MachineFunction {
|
|||
// The alignment of the function.
|
||||
unsigned Alignment;
|
||||
|
||||
// The currently active call_site value
|
||||
unsigned CallSiteIndex;
|
||||
|
||||
// The largest call_site value encountered
|
||||
unsigned MaxCallSiteIndex;
|
||||
|
||||
// Call sites mapped to corresponding landing pads
|
||||
std::map<MachineBasicBlock*, unsigned> LandingPadCallSiteIndexMap;
|
||||
|
||||
public:
|
||||
MachineFunction(Function *Fn, const TargetMachine &TM);
|
||||
~MachineFunction();
|
||||
|
@ -159,6 +169,41 @@ public:
|
|||
///
|
||||
void setAlignment(unsigned A) { Alignment = A; }
|
||||
|
||||
/// getCallSiteIndex() - Get the current call site index
|
||||
///
|
||||
unsigned getCallSiteIndex() { return CallSiteIndex; }
|
||||
|
||||
/// setCallSiteIndex() - Set the current call site index
|
||||
///
|
||||
void setCallSiteIndex(unsigned Idx) {
|
||||
CallSiteIndex = Idx;
|
||||
if (CallSiteIndex > MaxCallSiteIndex)
|
||||
MaxCallSiteIndex = CallSiteIndex;
|
||||
}
|
||||
|
||||
/// getMaxCallSiteIndex() - Get the largest call site index issued
|
||||
///
|
||||
unsigned getMaxCallSiteIndex() { return MaxCallSiteIndex; }
|
||||
|
||||
/// setCallSiteIndexLandingPad() - Map the call site to a landing pad
|
||||
///
|
||||
void setLandingPadCallSiteIndex(MachineBasicBlock *LandingPad,
|
||||
unsigned CallSite) {
|
||||
LandingPadCallSiteIndexMap[LandingPad] = CallSite;
|
||||
}
|
||||
|
||||
/// getCallSiteIndexLandingPad() - Get landing pad for the call site index
|
||||
///
|
||||
unsigned getLandingPadCallSiteIndex(MachineBasicBlock *LandingPad) {
|
||||
return LandingPadCallSiteIndexMap[LandingPad];
|
||||
}
|
||||
|
||||
/// getCallSiteCount() - Get the count of call site entries
|
||||
///
|
||||
unsigned getCallSiteCount() {
|
||||
return LandingPadCallSiteIndexMap.size();
|
||||
}
|
||||
|
||||
/// MachineFunctionInfo - Keep track of various per-function pieces of
|
||||
/// information for backends that would like to do so.
|
||||
///
|
||||
|
|
|
@ -121,6 +121,10 @@ namespace ISD {
|
|||
// address of the exception block on entry to an landing pad block.
|
||||
EXCEPTIONADDR,
|
||||
|
||||
// RESULT, OUTCHAIN = LSDAADDR(INCHAIN) - This node represents the
|
||||
// address of the Language Specific Data Area for the enclosing function.
|
||||
LSDAADDR,
|
||||
|
||||
// RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node represents
|
||||
// the selection index of the exception thrown.
|
||||
EHSELECTION,
|
||||
|
|
|
@ -305,8 +305,10 @@ def int_eh_unwind_init: Intrinsic<[llvm_void_ty]>,
|
|||
def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>;
|
||||
|
||||
let Properties = [IntrNoMem] in {
|
||||
def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
|
||||
def int_eh_sjlj_longjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty, llvm_i32_ty]>;
|
||||
def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
|
||||
def int_eh_sjlj_longjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty]>;
|
||||
def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>;
|
||||
def int_eh_sjlj_callsite: Intrinsic<[llvm_void_ty], [llvm_i32_ty]>;
|
||||
}
|
||||
|
||||
//===---------------- Generic Variable Attribute Intrinsics----------------===//
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace llvm {
|
|||
|
||||
/// TargetAsmInfo - This class is intended to be used as a base class for asm
|
||||
/// properties and features specific to the target.
|
||||
namespace ExceptionHandling { enum ExceptionsType { None, Dwarf, SjLj }; }
|
||||
|
||||
class TargetAsmInfo {
|
||||
protected:
|
||||
//===------------------------------------------------------------------===//
|
||||
|
@ -269,7 +271,8 @@ namespace llvm {
|
|||
/// SupportsExceptionHandling - True if target supports
|
||||
/// exception handling.
|
||||
///
|
||||
bool SupportsExceptionHandling; // Defaults to false.
|
||||
// Defaults to None
|
||||
ExceptionHandling::ExceptionsType ExceptionsType;
|
||||
|
||||
/// RequiresFrameSection - true if the Dwarf2 output needs a frame section
|
||||
///
|
||||
|
@ -482,7 +485,10 @@ namespace llvm {
|
|||
return SupportsDebugInformation;
|
||||
}
|
||||
bool doesSupportExceptionHandling() const {
|
||||
return SupportsExceptionHandling;
|
||||
return ExceptionsType != ExceptionHandling::None;
|
||||
}
|
||||
ExceptionHandling::ExceptionsType getExceptionHandlingType() const {
|
||||
return ExceptionsType;
|
||||
}
|
||||
bool doesDwarfRequireFrameSection() const {
|
||||
return DwarfRequiresFrameSection;
|
||||
|
|
|
@ -94,10 +94,14 @@ namespace llvm {
|
|||
/// .bss section. This flag disables such behaviour (necessary, e.g. for
|
||||
/// crt*.o compiling).
|
||||
extern bool NoZerosInBSS;
|
||||
|
||||
/// ExceptionHandling - This flag indicates that exception information should
|
||||
/// be emitted.
|
||||
extern bool ExceptionHandling;
|
||||
|
||||
/// DwarfExceptionHandling - This flag indicates that Dwarf exception
|
||||
/// information should be emitted.
|
||||
extern bool DwarfExceptionHandling;
|
||||
|
||||
/// SjLjExceptionHandling - This flag indicates that SJLJ exception
|
||||
/// information should be emitted.
|
||||
extern bool SjLjExceptionHandling;
|
||||
|
||||
/// UnwindTablesMandatory - This flag indicates that unwind tables should
|
||||
/// be emitted for all functions.
|
||||
|
|
|
@ -364,6 +364,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
|
|||
/// try-range address.
|
||||
void DwarfException::
|
||||
ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
|
||||
std::map<unsigned,CallSiteEntry*> &CallSiteIndexMap,
|
||||
const RangeMapType &PadMap,
|
||||
const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
|
||||
const SmallVectorImpl<unsigned> &FirstActions) {
|
||||
|
@ -405,10 +406,12 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
|
|||
assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
|
||||
"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) {
|
||||
if (SawPotentiallyThrowing &&
|
||||
TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) {
|
||||
CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
|
||||
CallSites.push_back(Site);
|
||||
PreviousIsInvoke = false;
|
||||
|
@ -435,6 +438,12 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
|
|||
|
||||
// Otherwise, create a new call-site.
|
||||
CallSites.push_back(Site);
|
||||
// For SjLj handling, map the call site entry to its index
|
||||
if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) {
|
||||
unsigned Index =
|
||||
MF->getLandingPadCallSiteIndex(LandingPad->LandingPadBlock);
|
||||
CallSiteIndexMap[Index] = &CallSites.back();
|
||||
}
|
||||
PreviousIsInvoke = true;
|
||||
} else {
|
||||
// Create a gap.
|
||||
|
@ -446,7 +455,8 @@ 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) {
|
||||
if (SawPotentiallyThrowing &&
|
||||
TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) {
|
||||
CallSiteEntry Site = {LastLabel, 0, 0, 0};
|
||||
CallSites.push_back(Site);
|
||||
}
|
||||
|
@ -496,7 +506,7 @@ void DwarfException::EmitExceptionTable() {
|
|||
|
||||
// Invokes and nounwind calls have entries in PadMap (due to being bracketed
|
||||
// by try-range labels when lowered). Ordinary calls do not, so appropriate
|
||||
// try-ranges for them need be deduced.
|
||||
// try-ranges for them need be deduced when using Dwarf exception handling.
|
||||
RangeMapType PadMap;
|
||||
for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
|
||||
const LandingPadInfo *LandingPad = LandingPads[i];
|
||||
|
@ -510,7 +520,9 @@ void DwarfException::EmitExceptionTable() {
|
|||
|
||||
// Compute the call-site table.
|
||||
SmallVector<CallSiteEntry, 64> CallSites;
|
||||
ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions);
|
||||
std::map<unsigned,CallSiteEntry*> CallSiteIndexMap;
|
||||
ComputeCallSiteTable(CallSites, CallSiteIndexMap, PadMap,
|
||||
LandingPads, FirstActions);
|
||||
|
||||
// Final tallies.
|
||||
|
||||
|
@ -518,12 +530,19 @@ void DwarfException::EmitExceptionTable() {
|
|||
const unsigned SiteStartSize = sizeof(int32_t); // DW_EH_PE_udata4
|
||||
const unsigned SiteLengthSize = sizeof(int32_t); // DW_EH_PE_udata4
|
||||
const unsigned LandingPadSize = sizeof(int32_t); // DW_EH_PE_udata4
|
||||
unsigned SizeSites = CallSites.size() * (SiteStartSize +
|
||||
SiteLengthSize +
|
||||
LandingPadSize);
|
||||
for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
|
||||
unsigned SizeSites;
|
||||
if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) {
|
||||
SizeSites = (MF->getMaxCallSiteIndex() - CallSites.size()) *
|
||||
TargetAsmInfo::getULEB128Size(0) * 2;
|
||||
} else
|
||||
SizeSites = CallSites.size() *
|
||||
(SiteStartSize + SiteLengthSize + LandingPadSize);
|
||||
for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
|
||||
SizeSites += TargetAsmInfo::getULEB128Size(CallSites[i].Action);
|
||||
|
||||
if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj)
|
||||
SizeSites += TargetAsmInfo::getULEB128Size(i);
|
||||
// FIXME: 'i' above should be the landing pad index
|
||||
}
|
||||
// Type infos.
|
||||
const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr
|
||||
unsigned SizeTypes = TypeInfos.size() * TypeInfoSize;
|
||||
|
@ -551,6 +570,11 @@ void DwarfException::EmitExceptionTable() {
|
|||
}
|
||||
|
||||
EmitLabel("exception", SubprogramCount);
|
||||
if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) {
|
||||
std::string SjLjName = "_lsda_";
|
||||
SjLjName += MF->getFunction()->getName().str();
|
||||
EmitLabel(SjLjName.c_str(), 0);
|
||||
}
|
||||
|
||||
// Emit the header.
|
||||
Asm->EmitInt8(dwarf::DW_EH_PE_omit);
|
||||
|
@ -600,54 +624,102 @@ void DwarfException::EmitExceptionTable() {
|
|||
Asm->EOL("TType base offset");
|
||||
}
|
||||
#else
|
||||
Asm->EmitInt8(dwarf::DW_EH_PE_absptr);
|
||||
Asm->EOL("TType format (DW_EH_PE_absptr)");
|
||||
Asm->EmitULEB128Bytes(TypeOffset);
|
||||
Asm->EOL("TType base offset");
|
||||
// For SjLj exceptions, is there is no TypeInfo, then we just explicitly
|
||||
// say that we're omitting that bit.
|
||||
// FIXME: does this apply to Dwarf also? The above #if 0 implies yes?
|
||||
if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj
|
||||
&& (TypeInfos.empty() || FilterIds.empty())) {
|
||||
Asm->EmitInt8(dwarf::DW_EH_PE_omit);
|
||||
Asm->EOL("TType format (DW_EH_PE_omit)");
|
||||
} else {
|
||||
Asm->EmitInt8(dwarf::DW_EH_PE_absptr);
|
||||
Asm->EOL("TType format (DW_EH_PE_absptr)");
|
||||
Asm->EmitULEB128Bytes(TypeOffset);
|
||||
Asm->EOL("TType base offset");
|
||||
}
|
||||
#endif
|
||||
|
||||
Asm->EmitInt8(dwarf::DW_EH_PE_udata4);
|
||||
Asm->EOL("Call site format (DW_EH_PE_udata4)");
|
||||
Asm->EmitULEB128Bytes(SizeSites);
|
||||
Asm->EOL("Call-site table length");
|
||||
// SjLj Exception handilng
|
||||
if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) {
|
||||
Asm->EmitInt8(dwarf::DW_EH_PE_udata4);
|
||||
Asm->EOL("Call site format (DW_EH_PE_udata4)");
|
||||
Asm->EmitULEB128Bytes(SizeSites);
|
||||
Asm->EOL("Call-site table length");
|
||||
|
||||
// Emit the landing pad site information.
|
||||
for (SmallVectorImpl<CallSiteEntry>::const_iterator
|
||||
I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
|
||||
const CallSiteEntry &S = *I;
|
||||
const char *BeginTag;
|
||||
unsigned BeginNumber;
|
||||
|
||||
if (!S.BeginLabel) {
|
||||
BeginTag = "eh_func_begin";
|
||||
BeginNumber = SubprogramCount;
|
||||
} else {
|
||||
BeginTag = "label";
|
||||
BeginNumber = S.BeginLabel;
|
||||
assert(MF->getCallSiteCount() == CallSites.size());
|
||||
|
||||
// Emit the landing pad site information.
|
||||
// SjLj handling assigned the call site indices in the front end, so
|
||||
// we need to make sure the table here lines up with that. That's pretty
|
||||
// horrible, and should be fixed ASAP to do that stuff in the back end
|
||||
// instead.
|
||||
std::map<unsigned, CallSiteEntry*>::const_iterator I, E;
|
||||
I = CallSiteIndexMap.begin();
|
||||
E = CallSiteIndexMap.end();
|
||||
for (unsigned CurrIdx = 1; I != E; ++I) {
|
||||
// paranoia.
|
||||
assert(CurrIdx <= I->first);
|
||||
// Fill in any gaps in the table
|
||||
while (CurrIdx++ < I->first) {
|
||||
Asm->EmitULEB128Bytes(0);
|
||||
Asm->EOL("Filler landing pad");
|
||||
Asm->EmitULEB128Bytes(0);
|
||||
Asm->EOL("Filler action");
|
||||
}
|
||||
const CallSiteEntry &S = *(I->second);
|
||||
Asm->EmitULEB128Bytes(I->first - 1);
|
||||
Asm->EOL("Landing pad");
|
||||
Asm->EmitULEB128Bytes(S.Action);
|
||||
Asm->EOL("Action");
|
||||
}
|
||||
} else {
|
||||
// DWARF Exception handling
|
||||
assert(TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf);
|
||||
|
||||
EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
|
||||
true, true);
|
||||
Asm->EOL("Region start");
|
||||
Asm->EmitInt8(dwarf::DW_EH_PE_udata4);
|
||||
Asm->EOL("Call site format (DW_EH_PE_udata4)");
|
||||
Asm->EmitULEB128Bytes(SizeSites);
|
||||
Asm->EOL("Call-site table length");
|
||||
|
||||
if (!S.EndLabel)
|
||||
EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber,
|
||||
true);
|
||||
else
|
||||
EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true);
|
||||
// Emit the landing pad site information.
|
||||
for (SmallVectorImpl<CallSiteEntry>::const_iterator
|
||||
I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
|
||||
const CallSiteEntry &S = *I;
|
||||
const char *BeginTag;
|
||||
unsigned BeginNumber;
|
||||
|
||||
Asm->EOL("Region length");
|
||||
if (!S.BeginLabel) {
|
||||
BeginTag = "eh_func_begin";
|
||||
BeginNumber = SubprogramCount;
|
||||
} else {
|
||||
BeginTag = "label";
|
||||
BeginNumber = S.BeginLabel;
|
||||
}
|
||||
|
||||
if (!S.PadLabel)
|
||||
Asm->EmitInt32(0);
|
||||
else
|
||||
EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
|
||||
EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount,
|
||||
true, true);
|
||||
Asm->EOL("Region start");
|
||||
|
||||
Asm->EOL("Landing pad");
|
||||
if (!S.EndLabel)
|
||||
EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber,
|
||||
true);
|
||||
else
|
||||
EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true);
|
||||
|
||||
Asm->EmitULEB128Bytes(S.Action);
|
||||
Asm->EOL("Action");
|
||||
Asm->EOL("Region length");
|
||||
|
||||
if (!S.PadLabel)
|
||||
Asm->EmitInt32(0);
|
||||
else
|
||||
EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount,
|
||||
true, true);
|
||||
|
||||
Asm->EOL("Landing pad");
|
||||
|
||||
Asm->EmitULEB128Bytes(S.Action);
|
||||
Asm->EOL("Action");
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the actions.
|
||||
|
@ -690,6 +762,8 @@ void DwarfException::EmitExceptionTable() {
|
|||
/// EndModule - Emit all exception information that should come after the
|
||||
/// content.
|
||||
void DwarfException::EndModule() {
|
||||
if (TAI->getExceptionHandlingType() != ExceptionHandling::Dwarf)
|
||||
return;
|
||||
if (TimePassesIsEnabled)
|
||||
ExceptionTimer->startTimer();
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ class VISIBILITY_HIDDEN DwarfException : public Dwarf {
|
|||
/// of any entry - they form gaps in the table. Entries must be ordered by
|
||||
/// try-range address.
|
||||
void ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
|
||||
std::map<unsigned,CallSiteEntry*> &CallSiteIndexMap,
|
||||
const RangeMapType &PadMap,
|
||||
const SmallVectorImpl<const LandingPadInfo *> &LPs,
|
||||
const SmallVectorImpl<unsigned> &FirstActions);
|
||||
|
|
|
@ -229,10 +229,17 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
|
|||
|
||||
// Turn exception handling constructs into something the code generators can
|
||||
// handle.
|
||||
if (!getTargetAsmInfo()->doesSupportExceptionHandling())
|
||||
PM.add(createLowerInvokePass(getTargetLowering()));
|
||||
else
|
||||
switch (getTargetAsmInfo()->getExceptionHandlingType())
|
||||
{
|
||||
// SjLj piggy-backs on dwarf for this bit
|
||||
case ExceptionHandling::SjLj:
|
||||
case ExceptionHandling::Dwarf:
|
||||
PM.add(createDwarfEHPass(getTargetLowering(), OptLevel==CodeGenOpt::None));
|
||||
break;
|
||||
case ExceptionHandling::None:
|
||||
PM.add(createLowerInvokePass(getTargetLowering()));
|
||||
break;
|
||||
}
|
||||
|
||||
PM.add(createGCLoweringPass());
|
||||
|
||||
|
|
|
@ -93,6 +93,9 @@ MachineFunction::MachineFunction(Function *F,
|
|||
MachineConstantPool(TM.getTargetData());
|
||||
Alignment = TM.getTargetLowering()->getFunctionAlignment(F);
|
||||
|
||||
CallSiteIndex = 0;
|
||||
MaxCallSiteIndex = 0;
|
||||
|
||||
// Set up jump table.
|
||||
const TargetData &TD = *TM.getTargetData();
|
||||
bool IsPic = TM.getRelocationModel() == Reloc::PIC_;
|
||||
|
|
|
@ -5198,6 +5198,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
|||
case ISD::FRAMEADDR: return "FRAMEADDR";
|
||||
case ISD::FRAME_TO_ARGS_OFFSET: return "FRAME_TO_ARGS_OFFSET";
|
||||
case ISD::EXCEPTIONADDR: return "EXCEPTIONADDR";
|
||||
case ISD::LSDAADDR: return "LSDAADDR";
|
||||
case ISD::EHSELECTION: return "EHSELECTION";
|
||||
case ISD::EH_RETURN: return "EH_RETURN";
|
||||
case ISD::ConstantPool: return "ConstantPool";
|
||||
|
|
|
@ -4087,7 +4087,11 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
|
|||
Offset));
|
||||
return 0;
|
||||
}
|
||||
|
||||
case Intrinsic::eh_sjlj_callsite: {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
MF.setCallSiteIndex(cast<ConstantSDNode>(getValue(I.getOperand(1)))->getZExtValue());
|
||||
return 0;
|
||||
}
|
||||
case Intrinsic::convertff:
|
||||
case Intrinsic::convertfsi:
|
||||
case Intrinsic::convertfui:
|
||||
|
@ -4451,9 +4455,14 @@ void SelectionDAGLowering::LowerCallTo(CallSite CS, SDValue Callee,
|
|||
}
|
||||
|
||||
if (LandingPad && MMI) {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
// Insert a label before the invoke call to mark the try range. This can be
|
||||
// used to detect deletion of the invoke via the MachineModuleInfo.
|
||||
BeginLabel = MMI->NextLabelID();
|
||||
|
||||
// Map this landing pad to the current call site entry
|
||||
MF.setLandingPadCallSiteIndex(LandingPad, MF.getCallSiteIndex());
|
||||
|
||||
// Both PendingLoads and PendingExports must be flushed here;
|
||||
// this call might not return.
|
||||
(void)getRoot();
|
||||
|
|
|
@ -511,11 +511,11 @@ namespace {
|
|||
DOUT << "JIT is managing a GOT\n";
|
||||
}
|
||||
|
||||
if (ExceptionHandling) DE = new JITDwarfEmitter(jit);
|
||||
if (DwarfExceptionHandling) DE = new JITDwarfEmitter(jit);
|
||||
}
|
||||
~JITEmitter() {
|
||||
delete MemMgr;
|
||||
if (ExceptionHandling) delete DE;
|
||||
if (DwarfExceptionHandling) delete DE;
|
||||
}
|
||||
|
||||
/// classof - Methods for support type inquiry through isa, cast, and
|
||||
|
@ -603,7 +603,7 @@ namespace {
|
|||
|
||||
virtual void setModuleInfo(MachineModuleInfo* Info) {
|
||||
MMI = Info;
|
||||
if (ExceptionHandling) DE->setModuleInfo(Info);
|
||||
if (DwarfExceptionHandling) DE->setModuleInfo(Info);
|
||||
}
|
||||
|
||||
void setMemoryExecutable(void) {
|
||||
|
@ -1125,7 +1125,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if (ExceptionHandling) {
|
||||
if (DwarfExceptionHandling) {
|
||||
uintptr_t ActualSize = 0;
|
||||
SavedBufferBegin = BufferBegin;
|
||||
SavedBufferEnd = BufferEnd;
|
||||
|
|
|
@ -34,7 +34,7 @@ ARMConstantPoolValue::ARMConstantPoolValue(const char *s, unsigned id,
|
|||
const char *Modif,
|
||||
bool AddCA)
|
||||
: MachineConstantPoolValue((const Type*)Type::Int32Ty),
|
||||
GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj),
|
||||
GV(NULL), S(strdup(s)), LabelId(id), Kind(k), PCAdjust(PCAdj),
|
||||
Modifier(Modif), AddCurrentAddress(AddCA) {}
|
||||
|
||||
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv,
|
||||
|
|
|
@ -53,6 +53,8 @@ public:
|
|||
bool AddCurrentAddress = false);
|
||||
ARMConstantPoolValue(GlobalValue *GV, ARMCP::ARMCPKind Kind,
|
||||
const char *Modifier);
|
||||
ARMConstantPoolValue();
|
||||
~ARMConstantPoolValue() {free((void*)S);}
|
||||
|
||||
|
||||
GlobalValue *getGV() const { return GV; }
|
||||
|
|
|
@ -1392,6 +1392,37 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) {
|
|||
EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
|
||||
return DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
|
||||
}
|
||||
case Intrinsic::eh_sjlj_lsda: {
|
||||
// blah. horrible, horrible hack with the forced magic name.
|
||||
// really need to clean this up. It belongs in the target-independent
|
||||
// layer somehow that doesn't require the coupling with the asm
|
||||
// printer.
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
EVT PtrVT = getPointerTy();
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
||||
SDValue CPAddr;
|
||||
unsigned PCAdj = (RelocM != Reloc::PIC_)
|
||||
? 0 : (Subtarget->isThumb() ? 4 : 8);
|
||||
ARMCP::ARMCPKind Kind = ARMCP::CPValue;
|
||||
// Save off the LSDA name for the AsmPrinter to use when it's time
|
||||
// to emit the table
|
||||
std::string LSDAName = "L_lsda_";
|
||||
LSDAName += MF.getFunction()->getName();
|
||||
ARMConstantPoolValue *CPV =
|
||||
new ARMConstantPoolValue(LSDAName.c_str(), ARMPCLabelIndex, Kind, PCAdj);
|
||||
CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, EVT::i32, CPAddr);
|
||||
SDValue Result =
|
||||
DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, NULL, 0);
|
||||
SDValue Chain = Result.getValue(1);
|
||||
|
||||
if (RelocM == Reloc::PIC_) {
|
||||
SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex++, EVT::i32);
|
||||
Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
case Intrinsic::eh_sjlj_setjmp:
|
||||
return DAG.getNode(ARMISD::EH_SJLJ_SETJMP, dl, EVT::i32, Op.getOperand(1));
|
||||
}
|
||||
|
|
|
@ -1427,9 +1427,12 @@ let Defs =
|
|||
def Int_eh_sjlj_setjmp : XI<(outs), (ins GPR:$src),
|
||||
AddrModeNone, SizeSpecial, IndexModeNone,
|
||||
Pseudo, NoItinerary,
|
||||
"add r0, pc, #4\n\t"
|
||||
"str r0, [$src, #+4]\n\t"
|
||||
"mov r0, #0 @ eh_setjmp", "",
|
||||
"str sp, [$src, #+8] @ eh_setjmp begin\n\t"
|
||||
"add ip, pc, #8\n\t"
|
||||
"str ip, [$src, #+4]\n\t"
|
||||
"mov r0, #0\n\t"
|
||||
"add pc, pc, #0\n\t"
|
||||
"mov r0, #1 @ eh_setjmp end\n\t", "",
|
||||
[(set R0, (ARMeh_sjlj_setjmp GPR:$src))]>;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,12 @@ ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo() {
|
|||
ProtectedDirective = NULL;
|
||||
HasDotTypeDotSizeDirective = false;
|
||||
SupportsDebugInformation = true;
|
||||
|
||||
// Exceptions handling
|
||||
ExceptionsType = ExceptionHandling::SjLj;
|
||||
GlobalEHDirective = "\t.globl\t";
|
||||
SupportsWeakOmittedEHFrame = false;
|
||||
AbsoluteEHSectionOffsets = false;
|
||||
}
|
||||
|
||||
ARMELFTargetAsmInfo::ARMELFTargetAsmInfo() {
|
||||
|
|
|
@ -208,6 +208,8 @@ namespace {
|
|||
} else {
|
||||
if (GV)
|
||||
Name = Mang->getMangledName(GV);
|
||||
else if (!strncmp(ACPV->getSymbol(), "L_lsda_", 7))
|
||||
Name = ACPV->getSymbol();
|
||||
else
|
||||
Name = Mang->makeNameProper(ACPV->getSymbol());
|
||||
}
|
||||
|
|
|
@ -37,6 +37,6 @@ SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo() {
|
|||
|
||||
// Exception handling is not supported on CellSPU (think about it: you only
|
||||
// have 256K for code+data. Would you support exception handling?)
|
||||
SupportsExceptionHandling = false;
|
||||
ExceptionsType = ExceptionHandling::None;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ PPCDarwinTargetAsmInfo::PPCDarwinTargetAsmInfo(const PPCTargetMachine &TM) :
|
|||
PCSymbol = ".";
|
||||
CommentString = ";";
|
||||
UsedDirective = "\t.no_dead_strip\t";
|
||||
SupportsExceptionHandling = true;
|
||||
|
||||
ExceptionsType = ExceptionHandling::Dwarf;
|
||||
|
||||
GlobalEHDirective = "\t.globl\t";
|
||||
SupportsWeakOmittedEHFrame = false;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ PPCLinuxTargetAsmInfo::PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM) :
|
|||
|
||||
// Exceptions handling
|
||||
if (!TM.getSubtargetImpl()->isPPC64())
|
||||
SupportsExceptionHandling = true;
|
||||
ExceptionsType = ExceptionHandling::Dwarf;
|
||||
AbsoluteEHSectionOffsets = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ TargetAsmInfo::TargetAsmInfo() {
|
|||
HasLEB128 = false;
|
||||
HasDotLocAndDotFile = false;
|
||||
SupportsDebugInformation = false;
|
||||
SupportsExceptionHandling = false;
|
||||
ExceptionsType = ExceptionHandling::None;
|
||||
DwarfRequiresFrameSection = true;
|
||||
DwarfUsesInlineInfoSection = false;
|
||||
Is_EHSymbolPrivate = true;
|
||||
|
|
|
@ -33,7 +33,8 @@ namespace llvm {
|
|||
FloatABI::ABIType FloatABIType;
|
||||
bool NoImplicitFloat;
|
||||
bool NoZerosInBSS;
|
||||
bool ExceptionHandling;
|
||||
bool DwarfExceptionHandling;
|
||||
bool SjLjExceptionHandling;
|
||||
bool UnwindTablesMandatory;
|
||||
Reloc::Model RelocationModel;
|
||||
CodeModel::Model CMModel;
|
||||
|
@ -104,9 +105,14 @@ DontPlaceZerosInBSS("nozero-initialized-in-bss",
|
|||
cl::location(NoZerosInBSS),
|
||||
cl::init(false));
|
||||
static cl::opt<bool, true>
|
||||
EnableExceptionHandling("enable-eh",
|
||||
EnableDwarfExceptionHandling("enable-eh",
|
||||
cl::desc("Emit DWARF exception handling (default if target supports)"),
|
||||
cl::location(ExceptionHandling),
|
||||
cl::location(DwarfExceptionHandling),
|
||||
cl::init(false));
|
||||
static cl::opt<bool, true>
|
||||
EnableSjLjExceptionHandling("enable-sjlj-eh",
|
||||
cl::desc("Emit SJLJ exception handling (default if target supports)"),
|
||||
cl::location(SjLjExceptionHandling),
|
||||
cl::init(false));
|
||||
static cl::opt<bool, true>
|
||||
EnableUnwindTables("unwind-tables",
|
||||
|
|
|
@ -77,7 +77,7 @@ X86DarwinTargetAsmInfo::X86DarwinTargetAsmInfo(const X86TargetMachine &TM):
|
|||
DwarfUsesInlineInfoSection = true;
|
||||
|
||||
// Exceptions handling
|
||||
SupportsExceptionHandling = true;
|
||||
ExceptionsType = ExceptionHandling::Dwarf;
|
||||
GlobalEHDirective = "\t.globl\t";
|
||||
SupportsWeakOmittedEHFrame = false;
|
||||
AbsoluteEHSectionOffsets = false;
|
||||
|
@ -99,7 +99,7 @@ X86ELFTargetAsmInfo::X86ELFTargetAsmInfo(const X86TargetMachine &TM) :
|
|||
SupportsDebugInformation = true;
|
||||
|
||||
// Exceptions handling
|
||||
SupportsExceptionHandling = true;
|
||||
ExceptionsType = ExceptionHandling::Dwarf;
|
||||
AbsoluteEHSectionOffsets = false;
|
||||
|
||||
// On Linux we must declare when we can use a non-executable stack.
|
||||
|
|
|
@ -394,9 +394,19 @@ bool LTOCodeGenerator::generateAssemblyCode(formatted_raw_ostream& out,
|
|||
|
||||
Module* mergedModule = _linker.getModule();
|
||||
|
||||
// If target supports exception handling then enable it now.
|
||||
if ( _target->getTargetAsmInfo()->doesSupportExceptionHandling() )
|
||||
llvm::ExceptionHandling = true;
|
||||
// If target supports exception handling then enable it now.
|
||||
switch (_target->getTargetAsmInfo()->getExceptionHandlingType()) {
|
||||
case ExceptionHandling::Dwarf:
|
||||
llvm::DwarfExceptionHandling = true;
|
||||
break;
|
||||
case ExceptionHandling::SjLj:
|
||||
llvm::SjLjExceptionHandling = true;
|
||||
break;
|
||||
case ExceptionHandling::None:
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Unknown exception handling model!");
|
||||
}
|
||||
|
||||
// if options were requested, set them
|
||||
if ( !_codegenOptions.empty() )
|
||||
|
|
Loading…
Reference in New Issue