SjLj based exception handling unwinding support. This patch is nasty, brutish
authorJim Grosbach <grosbach@apple.com>
Tue, 11 Aug 2009 00:09:57 +0000 (00:09 +0000)
committerJim Grosbach <grosbach@apple.com>
Tue, 11 Aug 2009 00:09:57 +0000 (00:09 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78625 91177308-0d34-0410-b5e6-96231b3b80d8

25 files changed:
docs/ExceptionHandling.html
include/llvm/CodeGen/MachineFunction.h
include/llvm/CodeGen/SelectionDAGNodes.h
include/llvm/Intrinsics.td
include/llvm/Target/TargetAsmInfo.h
include/llvm/Target/TargetOptions.h
lib/CodeGen/AsmPrinter/DwarfException.cpp
lib/CodeGen/AsmPrinter/DwarfException.h
lib/CodeGen/LLVMTargetMachine.cpp
lib/CodeGen/MachineFunction.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
lib/ExecutionEngine/JIT/JITEmitter.cpp
lib/Target/ARM/ARMConstantPoolValue.cpp
lib/Target/ARM/ARMConstantPoolValue.h
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMTargetAsmInfo.cpp
lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
lib/Target/CellSPU/SPUTargetAsmInfo.cpp
lib/Target/PowerPC/PPCTargetAsmInfo.cpp
lib/Target/TargetAsmInfo.cpp
lib/Target/TargetMachine.cpp
lib/Target/X86/X86TargetAsmInfo.cpp
tools/lto/LTOCodeGenerator.cpp

index 6ec6ab8233eda346e9f77d1fe5b46912af363670..851ed1238be782e8375efb653379beb204b79e19 100644 (file)
@@ -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>
index 57c946c789a9d1a85783af4060dd1e38a952606c..f30cb821c1a34256be31604db12111fe87b1319b 100644 (file)
@@ -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.
   ///
index bbb1f3bd90bba068574101990300e4c0b78337da..7229463d4e5eb1c2c8714a14408d671a4181fbc2 100644 (file)
@@ -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,
index fa21dc0682ba82eb98a76beafe3ab7f7fb45c3e8..25f6604afab75b4e3d5b301ba0f2889bef95e837 100644 (file)
@@ -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----------------===//
index aa39c90c5a9aca4767a8c381e893b911c1f734ec..2dd644c089f5f44a6f8ac89fb3364e306f018dd0 100644 (file)
@@ -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;
index ccce2f0de857b9056e54ae821e6441596968d226..b27d49630a110ced4f45059a089d778dd8534479 100644 (file)
@@ -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.
index fec1ad7557377b9e06408aae842bbf5e795db7b3..a0cd456d372023b24bec0b447690daf25e82b256 100644 (file)
@@ -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();
 
index e165df4693d0e431ef47fd6fa7d18059ca48b177..ee390cff013ffb58ca60ac3fd4c762913b7d9ef9 100644 (file)
@@ -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);
index 8249501dc102afb76a6910c2fdda3304fb175996..c60f9c7e41062407b7a6b4d11912d32b8e3b6e55 100644 (file)
@@ -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());
 
index 2e9303aeefb90a8f131fe6d50a9d562a76bbb8a2..ab037c243a70dc956e8d1142d0130bb64c0a5018 100644 (file)
@@ -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_;
index 712fedad4de627036c8f2a381f84bfce3eee1376..7297d60d3469c4d76a69b94bd4bd8b022640dc69 100644 (file)
@@ -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";
index 01800696234cb7428f401bf388c02aac99a89b36..1d02bffb61a0d216620d51898615b457c60f0859 100644 (file)
@@ -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();
index af69ddffd28034102434cfde3631475f6c8bf41e..c3e16510b46073d0da8d66af77447771cf835a42 100644 (file)
@@ -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;
index a75ed3bd53396f1fc26a19080609c000a5e6801c..adf03e04b81027d24471a6ff9186f71302023f18 100644 (file)
@@ -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,
index fcaf2e6885a8ab3f9d7681f407f8e4e269099aa8..37a2c8047895c27f7db00cf8c38a5f8346ca648a 100644 (file)
@@ -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; }
index aedddaa20b867a5af374eae895867c9a78173278..61722d44faed340f35e074f8ab166b8adf82da82 100644 (file)
@@ -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));
   }
index 5190492b646a46a07ea1a37f4d19d086f8cff41b..4a2ce4be78cf616fb8da54519b2463981a9eed7e 100644 (file)
@@ -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))]>;
 }
 
index e3348a90d458c98749c8fd87dfbbcc6304facad9..653219bf744133fbe51117d10c7329093325451b 100644 (file)
@@ -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() {
index a909b66413f918c4761f1384dc35d6806196ec2b..9de9af60e6a3050413d78b265eb432e810a8fd2a 100644 (file)
@@ -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());
       }
index 2dcb1135c5708b12001955d6744d68098429a131..991afa0e0b0fe648449870ec6f724d80547f2bcd 100644 (file)
@@ -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;
 }
 
index 26120175fb9c69cf63b9f8e2bc0a534f137c49ea..52e29865fa511d50793ecb182a6ae262eaacb6d4 100644 (file)
@@ -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;
 }
 
index 6ac54e0bf0517798881f3cbb4311dccb3e32a05b..84a97710d6781c02e569a9ec2be8ba313dbdd659 100644 (file)
@@ -72,7 +72,7 @@ TargetAsmInfo::TargetAsmInfo() {
   HasLEB128 = false;
   HasDotLocAndDotFile = false;
   SupportsDebugInformation = false;
-  SupportsExceptionHandling = false;
+  ExceptionsType = ExceptionHandling::None;
   DwarfRequiresFrameSection = true;
   DwarfUsesInlineInfoSection = false;
   Is_EHSymbolPrivate = true;
index fb95c52a999e4ae38fa1032574ce80b433fcc025..b94fa68be92cda64f1bba5c348cec0016039edf1 100644 (file)
@@ -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",
index 297ebf594b077b564b9a9265f50f6b8fba4c8b21..b702cbfc44b252409087967c4b2e3773d43ed62e 100644 (file)
@@ -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.
index 598da7fa6649055078d0d035d99d1fdd9797fd2f..dacf483563f388fd5346ebce4e573e0850d1e6fd 100644 (file)
@@ -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() )