diff options
25 files changed, 333 insertions, 80 deletions
diff --git a/docs/ExceptionHandling.html b/docs/ExceptionHandling.html index 6ec6ab8233..851ed1238b 100644 --- a/docs/ExceptionHandling.html +++ b/docs/ExceptionHandling.html @@ -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> @@ -429,6 +431,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> </div> diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 57c946c789..f30cb821c1 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -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. /// diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index bbb1f3bd90..7229463d4e 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -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, diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index fa21dc0682..25f6604afa 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -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----------------===// diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index aa39c90c5a..2dd644c089 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -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; diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index ccce2f0de8..b27d49630a 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -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. diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index fec1ad7557..a0cd456d37 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -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"); + + + 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); + + 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 + // 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; + const CallSiteEntry &S = *I; + const char *BeginTag; + unsigned BeginNumber; - if (!S.BeginLabel) { - BeginTag = "eh_func_begin"; - BeginNumber = SubprogramCount; - } else { - BeginTag = "label"; - BeginNumber = S.BeginLabel; - } + if (!S.BeginLabel) { + BeginTag = "eh_func_begin"; + BeginNumber = SubprogramCount; + } else { + BeginTag = "label"; + BeginNumber = S.BeginLabel; + } - EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, - true, true); - Asm->EOL("Region start"); + EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, + true, true); + Asm->EOL("Region start"); - if (!S.EndLabel) - EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, - true); - else - EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); + if (!S.EndLabel) + EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, + true); + else + EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); - Asm->EOL("Region length"); + Asm->EOL("Region length"); - if (!S.PadLabel) - Asm->EmitInt32(0); - else - EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, - true, true); + if (!S.PadLabel) + Asm->EmitInt32(0); + else + EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, + true, true); - Asm->EOL("Landing pad"); + Asm->EOL("Landing pad"); - Asm->EmitULEB128Bytes(S.Action); - Asm->EOL("Action"); + 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(); diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index e165df4693..ee390cff01 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -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); diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 8249501dc1..c60f9c7e41 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -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()); diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index 2e9303aeef..ab037c243a 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -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_; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 712fedad4d..7297d60d34 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -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"; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 0180069623..1d02bffb61 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -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(); diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index af69ddffd2..c3e16510b4 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -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; diff --git a/lib/Target/ARM/ARMConstantPoolValue.cpp b/lib/Target/ARM/ARMConstantPoolValue.cpp index a75ed3bd53..adf03e04b8 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -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, diff --git a/lib/Target/ARM/ARMConstantPoolValue.h b/lib/Target/ARM/ARMConstantPoolValue.h index fcaf2e6885..37a2c80478 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.h +++ b/lib/Target/ARM/ARMConstantPoolValue.h @@ -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; } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index aedddaa20b..61722d44fa 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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)); } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 5190492b64..4a2ce4be78 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -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))]>; } diff --git a/lib/Target/ARM/ARMTargetAsmInfo.cpp b/lib/Target/ARM/ARMTargetAsmInfo.cpp index e3348a90d4..653219bf74 100644 --- a/lib/Target/ARM/ARMTargetAsmInfo.cpp +++ b/lib/Target/ARM/ARMTargetAsmInfo.cpp @@ -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() { diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index a909b66413..9de9af60e6 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -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()); } diff --git a/lib/Target/CellSPU/SPUTargetAsmInfo.cpp b/lib/Target/CellSPU/SPUTargetAsmInfo.cpp index 2dcb1135c5..991afa0e0b 100644 --- a/lib/Target/CellSPU/SPUTargetAsmInfo.cpp +++ b/lib/Target/CellSPU/SPUTargetAsmInfo.cpp @@ -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; } diff --git a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp index 26120175fb..52e29865fa 100644 --- a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp +++ b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp @@ -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; } diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp index 6ac54e0bf0..84a97710d6 100644 --- a/lib/Target/TargetAsmInfo.cpp +++ b/lib/Target/TargetAsmInfo.cpp @@ -72,7 +72,7 @@ TargetAsmInfo::TargetAsmInfo() { HasLEB128 = false; HasDotLocAndDotFile = false; SupportsDebugInformation = false; - SupportsExceptionHandling = false; + ExceptionsType = ExceptionHandling::None; DwarfRequiresFrameSection = true; DwarfUsesInlineInfoSection = false; Is_EHSymbolPrivate = true; diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index fb95c52a99..b94fa68be9 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -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", diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp index 297ebf594b..b702cbfc44 100644 --- a/lib/Target/X86/X86TargetAsmInfo.cpp +++ b/lib/Target/X86/X86TargetAsmInfo.cpp @@ -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. diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 598da7fa66..dacf483563 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -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() ) |