[mono/llvm] 02356b76: Add support for Mono EH to the JIT and the static compiler. For the JIT, emit a variant of the C++ EH structures which contains extra information required by mono, i.e. the stack location of 'this'. For the static compiler, emit separate tables instead of the normal C++ tables.

"Zoltan Varga ([email protected])" <[email protected]> Tue, 12 Nov 2013 22:15:08 +0000
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <000001424e61e75f-6c8c9bf2-36d1-45af-9fa0-2e5583cfb149-000000@email.amazonses.com>
   Branch: refs/heads/mono2
     Home: https://github.com/mono/llvm
  Compare: https://github.com/mono/llvm/compare/fed612de3991...02356b76b137

   Commit: 02356b76b1377078cc44f7515d36f652273629f5
   Author: Zoltan Varga <[email protected]> (vargaz)
     Date: 2013-11-12 22:13:36 GMT
      URL: https://github.com/mono/llvm/commit/02356b76b1377078cc44f7515d36f652273629f5

Add support for Mono EH to the JIT and the static compiler. For the JIT, emit a variant of the C++ EH structures which contains extra information required by mono, i.e. the stack location of 'this'. For the static compiler, emit separate tables instead of the normal C++ tables.

Changed paths:
  M include/llvm/CodeGen/MachineFunction.h
  M include/llvm/MC/MCObjectFileInfo.h
  M lib/CodeGen/AsmPrinter/AsmPrinter.cpp
  M lib/CodeGen/AsmPrinter/DwarfException.cpp
  M lib/CodeGen/AsmPrinter/DwarfException.h
  M lib/CodeGen/MachineFunction.cpp
  M lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
  M lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
  M lib/MC/MCObjectFileInfo.cpp
  M lib/Transforms/Scalar/GlobalMerge.cpp
Added paths:
  A include/llvm/CodeGen/MonoMachineFunctionInfo.h
  A lib/CodeGen/AsmPrinter/DwarfMonoException.cpp

Modified: include/llvm/CodeGen/MachineFunction.h
===================================================================
@@ -40,6 +40,7 @@
 class TargetMachine;
 class TargetRegisterClass;
 struct MachinePointerInfo;
+class MonoMachineFunctionInfo;
 
 template <>
 struct ilist_traits<MachineBasicBlock>
@@ -134,6 +135,8 @@ class MachineFunction {
   /// True if the function includes MS-style inline assembly.
   bool HasMSInlineAsm;
 
+  MonoMachineFunctionInfo *MonoInfo;
+
   MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION;
   void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION;
 public:
@@ -192,6 +195,9 @@ class MachineFunction {
   MachineConstantPool *getConstantPool() { return ConstantPool; }
   const MachineConstantPool *getConstantPool() const { return ConstantPool; }
 
+  MonoMachineFunctionInfo *getMonoInfo() { return MonoInfo; }
+  const MonoMachineFunctionInfo *getMonoInfo() const { return MonoInfo; }
+
   /// getAlignment - Return the alignment (log2, not bytes) of the function.
   ///
   unsigned getAlignment() const { return Alignment; }

Added: include/llvm/CodeGen/MonoMachineFunctionInfo.h
===================================================================
@@ -0,0 +1,33 @@
+#ifndef LLVM_CODEGEN_MACHINMONOEFUNCTION_H
+#define LLVM_CODEGEN_MACHINMONOEFUNCTION_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+class MonoMachineFunctionInfo {
+
+  int ThisStackSlot;
+
+ public:
+
+  MonoMachineFunctionInfo(MachineFunction &MF) : ThisStackSlot (-1) {
+  }
+
+  virtual ~MonoMachineFunctionInfo () {
+  }
+
+  void setThisStackSlot (int slot) {
+	  ThisStackSlot = slot;
+  }
+
+  int getThisStackSlot () const {
+	  return ThisStackSlot;
+  }
+};
+
+}
+
+#endif

Modified: include/llvm/MC/MCObjectFileInfo.h
===================================================================
@@ -50,6 +50,7 @@ class MCObjectFileInfo {
   /// Section flags for eh_frame
   unsigned EHSectionType;
   unsigned EHSectionFlags;
+  unsigned MonoEHTableEncoding;
 
   /// CompactUnwindDwarfEHFrameOnly - Compact unwind encoding indicating that we
   /// should emit only an EH frame.
@@ -209,6 +210,7 @@ class MCObjectFileInfo {
     return CFI ? FDECFIEncoding : FDEEncoding;
   }
   unsigned getTTypeEncoding() const { return TTypeEncoding; }
+  unsigned getMonoEHTableEncoding() const { return MonoEHTableEncoding; }
 
   unsigned getCompactUnwindDwarfEHFrameOnly() const {
     return CompactUnwindDwarfEHFrameOnly;

Modified: lib/CodeGen/AsmPrinter/AsmPrinter.cpp
===================================================================
@@ -37,6 +37,7 @@
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/MathExtras.h"
@@ -56,6 +57,9 @@
 
 STATISTIC(EmittedInsts, "Number of machine instrs printed");
 
+cl::opt<bool> EnableMonoEH("enable-mono-eh-frame", cl::NotHidden,
+     cl::desc("Enable generation of Mono specific EH tables"));
+
 char AsmPrinter::ID = 0;
 
 typedef DenseMap<GCStrategy*,GCMetadataPrinter*> gcp_map_type;
@@ -194,6 +198,11 @@ bool AsmPrinter::doInitialization(Module &M) {
   if (MAI->doesSupportDebugInformation())
     DD = new DwarfDebug(this, &M);
 
+  if (EnableMonoEH) {
+    DE = new DwarfMonoException(this);
+    return false;
+  }
+
   switch (MAI->getExceptionHandlingType()) {
   case ExceptionHandling::None:
     return false;
@@ -709,7 +718,10 @@ void AsmPrinter::EmitFunctionBody() {
 
       switch (II->getOpcode()) {
       case TargetOpcode::PROLOG_LABEL:
-        emitPrologLabel(*II);
+        if (EnableMonoEH)
+          OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol());
+        else
+          emitPrologLabel(*II);
         break;
 
       case TargetOpcode::EH_LABEL:

Modified: lib/CodeGen/AsmPrinter/DwarfException.cpp
===================================================================
@@ -19,6 +19,8 @@
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MonoMachineFunctionInfo.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/Module.h"
 #include "llvm/MC/MCAsmInfo.h"
@@ -27,6 +29,7 @@
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormattedStream.h"

Modified: lib/CodeGen/AsmPrinter/DwarfException.h
===================================================================
@@ -15,6 +15,8 @@
 #define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/IR/Module.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include <vector>
 
@@ -43,6 +45,17 @@ class DwarfException {
   /// MMI - Collected machine module information.
   MachineModuleInfo *MMI;
 
+  /// CallSiteEntry - Structure describing an entry in the call-site table.
+  struct CallSiteEntry {
+    // The 'try-range' is BeginLabel .. EndLabel.
+    MCSymbol *BeginLabel; // zero indicates the start of the function.
+    MCSymbol *EndLabel;   // zero indicates the end of the function.
+
+    // The landing pad starts at PadLabel.
+    MCSymbol *PadLabel;   // zero indicates that there is no landing pad.
+    unsigned Action;
+  };
+
   /// SharedTypeIds - How many leading type ids two landing pads have in common.
   static unsigned SharedTypeIds(const LandingPadInfo *L,
                                 const LandingPadInfo *R);
@@ -67,17 +80,45 @@ class DwarfException {
     unsigned Previous;
   };
 
-  /// CallSiteEntry - Structure describing an entry in the call-site table.
-  struct CallSiteEntry {
-    // The 'try-range' is BeginLabel .. EndLabel.
-    MCSymbol *BeginLabel; // zero indicates the start of the function.
-    MCSymbol *EndLabel;   // zero indicates the end of the function.
+  // Mono specific
+  struct MonoEHFrameInfo {
+    const MachineFunction *MF;
+    std::vector<CallSiteEntry> CallSites;
+    std::vector<const GlobalVariable *> TypeInfos;
+    std::vector<unsigned> FilterIds;
+    std::vector<LandingPadInfo> PadInfos;
+    int FunctionNumber;
+    int MonoMethodIdx;
+    int FrameReg;
+    int ThisOffset;
+  };
 
-    // The landing pad starts at PadLabel.
-    MCSymbol *PadLabel;   // zero indicates that there is no landing pad.
-    unsigned Action;
+  struct FunctionEHFrameInfo {
+    MCSymbol *FunctionEHSym;  // L_foo.eh
+    unsigned Number;
+    unsigned PersonalityIndex;
+    bool adjustsStack;
+    bool hasLandingPads;
+    std::vector<MCCFIInstruction> Instructions;
+    const Function *function;
+
+    MonoEHFrameInfo MonoEH;
+
+    FunctionEHFrameInfo(MCSymbol *EHSym, unsigned Num, unsigned P,
+                        bool hC, bool hL,
+                        const std::vector<MCCFIInstruction> &M,
+                        const Function *f):
+      FunctionEHSym(EHSym), Number(Num), PersonalityIndex(P),
+      adjustsStack(hC), hasLandingPads(hL), Instructions(M), function (f) { }
   };
 
+  std::vector<FunctionEHFrameInfo> EHFrames;
+
+  /// UsesLSDA - Indicates whether an FDE that uses the CIE at the given index
+  /// uses an LSDA. If so, then we need to encode that information in the CIE's
+  /// augmentation.
+  DenseMap<unsigned, bool> UsesLSDA;
+
   /// ComputeActionsTable - Compute the actions table and gather the first
   /// action index for each landing pad site.
   unsigned ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*>&LPs,
@@ -231,6 +272,36 @@ class Win64Exception : public DwarfException {
   virtual void EndFunction();
 };
 
+class DwarfMonoException : public DwarfException {
+
+  StringMap<int> FuncIndexes;
+
+public:
+  //===--------------------------------------------------------------------===//
+  // Main entry points.
+  //
+  DwarfMonoException(AsmPrinter *A);
+  virtual ~DwarfMonoException();
+
+  /// EndModule - Emit all exception information that should come after the
+  /// content.
+  virtual void EndModule();
+
+  /// BeginFunction - Gather pre-function exception information.  Assumes being
+  /// emitted immediately after the function entry point.
+  virtual void BeginFunction(const MachineFunction *MF);
+
+  /// EndFunction - Gather and emit post-function exception information.
+  virtual void EndFunction();
+
+  // EmitMonoEHFrame - Emit Mono specific exception handling tables
+  void EmitMonoEHFrame(const Function *Personality);
+
+  void PrepareMonoLSDA(FunctionEHFrameInfo *EHFrameInfo);
+
+  void EmitMonoLSDA(const FunctionEHFrameInfo *EHFrameInfo);
+};
+
 } // End of namespace llvm
 
 #endif

Added: lib/CodeGen/AsmPrinter/DwarfMonoException.cpp
===================================================================
@@ -0,0 +1,753 @@
+//===-- CodeGen/AsmPrinter/DwarfMonoException.cpp - Dwarf Exception Impl ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to emit Mono specific exception handling tables.
+// It is based on code in DwarfException.cpp and MCDwarf.cpp.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfException.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MonoMachineFunctionInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+using namespace llvm;
+
+// FIXME:
+static cl::opt<bool> DisableGNUEH("disable-gnu-eh-frame", cl::NotHidden,
+                                  cl::desc("Disable generation of GNU .eh_frame"));
+
+static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
+                                                  const MCSymbol &Start,
+                                                  const MCSymbol &End,
+                                                  int IntVal) {
+  MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+  const MCExpr *Res =
+    MCSymbolRefExpr::Create(&End, Variant, MCOS.getContext());
+  const MCExpr *RHS =
+    MCSymbolRefExpr::Create(&Start, Variant, MCOS.getContext());
+  const MCExpr *Res1 =
+    MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext());
+  const MCExpr *Res2 =
+    MCConstantExpr::Create(IntVal, MCOS.getContext());
+  const MCExpr *Res3 =
+    MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext());
+  return Res3;
+}
+
+void EmitCFIInstruction(MCStreamer &Streamer,
+                        const MCCFIInstruction &Instr,
+                        int &CFAOffset, int DataAlignmentFactor) {
+  // Same as MCDwarf::EmitCFIInstruction ()
+  // FIXME: Unify
+  int dataAlignmentFactor = DataAlignmentFactor;
+  bool VerboseAsm = Streamer.isVerboseAsm();
+
+  switch (Instr.getOperation()) {
+  case MCCFIInstruction::OpWindowSave: {
+    Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1);
+    return;
+  }
+  case MCCFIInstruction::OpUndefined: {
+    unsigned Reg = Instr.getRegister();
+    if (VerboseAsm) {
+      Streamer.AddComment("DW_CFA_undefined");
+      Streamer.AddComment(Twine("Reg ") + Twine(Reg));
+    }
+    Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1);
+    Streamer.EmitULEB128IntValue(Reg);
+    return;
+  }
+  case MCCFIInstruction::OpAdjustCfaOffset:
+  case MCCFIInstruction::OpDefCfaOffset: {
+    const bool IsRelative =
+      Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;
+
+    if (VerboseAsm)
+      Streamer.AddComment("DW_CFA_def_cfa_offset");
+    Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);
+
+    if (IsRelative)
+      CFAOffset += Instr.getOffset();
+    else
+      CFAOffset = -Instr.getOffset();
+
+    if (VerboseAsm)
+      Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
+    Streamer.EmitULEB128IntValue(CFAOffset);
+
+    return;
+  }
+  case MCCFIInstruction::OpDefCfa: {
+    if (VerboseAsm)
+      Streamer.AddComment("DW_CFA_def_cfa");
+    Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
+
+    if (VerboseAsm)
+      Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister()));
+    Streamer.EmitULEB128IntValue(Instr.getRegister());
+
+    CFAOffset = -Instr.getOffset();
+
+    if (VerboseAsm)
+      Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
+    Streamer.EmitULEB128IntValue(CFAOffset);
+
+    return;
+  }
+
+  case MCCFIInstruction::OpDefCfaRegister: {
+    if (VerboseAsm)
+      Streamer.AddComment("DW_CFA_def_cfa_register");
+    Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
+
+    if (VerboseAsm)
+      Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister()));
+    Streamer.EmitULEB128IntValue(Instr.getRegister());
+
+    return;
+  }
+
+  case MCCFIInstruction::OpOffset:
+  case MCCFIInstruction::OpRelOffset: {
+    const bool IsRelative =
+      Instr.getOperation() == MCCFIInstruction::OpRelOffset;
+
+    unsigned Reg = Instr.getRegister();
+    int Offset = Instr.getOffset();
+    if (IsRelative)
+      Offset -= CFAOffset;
+    Offset = Offset / dataAlignmentFactor;
+
+    if (Offset < 0) {
+      if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf");
+      Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1);
+      if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
+      Streamer.EmitULEB128IntValue(Reg);
+      if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
+      Streamer.EmitSLEB128IntValue(Offset);
+    } else if (Reg < 64) {
+      if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") +
+                                          Twine(Reg) + ")");
+      Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1);
+      if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
+      Streamer.EmitULEB128IntValue(Offset);
+    } else {
+      if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended");
+      Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1);
+      if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
+      Streamer.EmitULEB128IntValue(Reg);
+      if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
+      Streamer.EmitULEB128IntValue(Offset);
+    }
+    return;
+  }
+  case MCCFIInstruction::OpRememberState:
+    if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state");
+    Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1);
+    return;
+  case MCCFIInstruction::OpRestoreState:
+    if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state");
+    Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
+    return;
+  case MCCFIInstruction::OpSameValue: {
+    unsigned Reg = Instr.getRegister();
+    if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value");
+    Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1);
+    if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
+    Streamer.EmitULEB128IntValue(Reg);
+    return;
+  }
+  case MCCFIInstruction::OpRestore: {
+    unsigned Reg = Instr.getRegister();
+    if (VerboseAsm) {
+      Streamer.AddComment("DW_CFA_restore");
+      Streamer.AddComment(Twine("Reg ") + Twine(Reg));
+    }
+    Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
+    return;
+  }
+  case MCCFIInstruction::OpEscape:
+    if (VerboseAsm) Streamer.AddComment("Escape bytes");
+    Streamer.EmitBytes(Instr.getValues());
+    return;
+  case MCCFIInstruction::OpRegister:
+	  llvm_unreachable("Unhandled case in switch");	
+	  return;
+  }
+  llvm_unreachable("Unhandled case in switch");
+}
+
+/// EmitFrameMoves - Emit frame instructions to describe the layout of the
+/// frame.
+void EmitCFIInstructions(MCStreamer &streamer,
+                         const std::vector<MCCFIInstruction> &Instrs,
+                         MCSymbol *BaseLabel,
+                         int &CFAOffset,
+                         int DataAlignmentFactor) {
+  for (unsigned i = 0, N = Instrs.size(); i < N; ++i) {
+    const MCCFIInstruction &Instr = Instrs[i];
+    MCSymbol *Label = Instr.getLabel();
+    // Throw out move if the label is invalid.
+    //if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.
+
+    // Advance row if new location.
+    if (BaseLabel && Label) {
+      MCSymbol *ThisSym = Label;
+      if (ThisSym != BaseLabel) {
+        streamer.AddComment ("cfa_advance");
+        streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
+        BaseLabel = ThisSym;
+      }
+    }
+
+    EmitCFIInstruction(streamer, Instr, CFAOffset, DataAlignmentFactor);
+  }
+}
+
+/// PrepareMonoLSDA - Collect information needed by EmitMonoLSDA
+///
+///   This function collects information available only during EndFunction which is needed
+/// by EmitMonoLSDA and stores it into EHFrameInfo. It is the same as the
+/// beginning of EmitExceptionTable.
+///
+void DwarfMonoException::PrepareMonoLSDA(FunctionEHFrameInfo *EHFrameInfo) {
+  const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
+  const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
+  const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
+
+  // Sort the landing pads in order of their type ids.  This is used to fold
+  // duplicate actions.
+  SmallVector<const LandingPadInfo *, 64> LandingPads;
+  LandingPads.reserve(PadInfos.size());
+
+  for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
+    LandingPads.push_back(&PadInfos[i]);
+
+  std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
+
+  // Compute the actions table and gather the first action index for each
+  // landing pad site.
+  SmallVector<ActionEntry, 32> Actions;
+  SmallVector<unsigned, 64> FirstActions;
+  ComputeActionsTable(LandingPads, Actions, FirstActions);
+
+  // 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 when using DWARF exception handling.
+  RangeMapType PadMap;
+  for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
+    const LandingPadInfo *LandingPad = LandingPads[i];
+    for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
+      MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
+      assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
+      PadRange P = { i, j };
+      PadMap[BeginLabel] = P;
+    }
+  }
+
+  // Compute the call-site table.
+  SmallVector<CallSiteEntry, 64> CallSites;
+  ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions);
+
+  //
+  // Compute a mapping from method names to their AOT method index
+  //
+  if (FuncIndexes.size () == 0) {
+    const Module *m = MMI->getModule ();
+    NamedMDNode *indexes = m->getNamedMetadata ("mono.function_indexes");
+	if (indexes) {
+      for (unsigned int i = 0; i < indexes->getNumOperands (); ++i) {
+        MDNode *n = indexes->getOperand (i);
+        MDString *s = (MDString*)n->getOperand (0);
+        ConstantInt *idx = (ConstantInt*)n->getOperand (1);
+        FuncIndexes.GetOrCreateValue (s->getString (), (int)idx->getLimitedValue () + 1);
+      }
+    }
+  }
+
+  MonoEHFrameInfo *MonoEH = &EHFrameInfo->MonoEH;
+
+  // Save information for EmitMonoLSDA
+  MonoEH->MF = Asm->MF;
+  MonoEH->FunctionNumber = Asm->getFunctionNumber();
+  MonoEH->CallSites.insert(MonoEH->CallSites.begin(), CallSites.begin(), CallSites.end());
+  MonoEH->TypeInfos = TypeInfos;
+  MonoEH->FilterIds = FilterIds;
+  MonoEH->PadInfos = PadInfos;
+  MonoEH->MonoMethodIdx = FuncIndexes.lookup (Asm->MF->getFunction ()->getName ()) - 1;
+  //outs()<<"A:"<<Asm->MF->getFunction()->getName() << " " << MonoEH->MonoMethodIdx << "\n";
+
+  int ThisSlot = Asm->MF->getMonoInfo()->getThisStackSlot();
+
+  if (ThisSlot != -1) {
+    unsigned FrameReg;
+    MonoEH->ThisOffset = Asm->MF->getTarget ().getFrameLowering ()->getFrameIndexReference (*Asm->MF, ThisSlot, FrameReg);
+    MonoEH->FrameReg = Asm->MF->getTarget ().getRegisterInfo ()->getDwarfRegNum (FrameReg, true);
+  } else {
+    MonoEH->FrameReg = -1;
+  }
+}
+
+/// EmitMonoLSDA - Mono's version of EmitExceptionTable
+///
+///   We emit the information inline instead of into a separate section.
+///
+void DwarfMonoException::EmitMonoLSDA(const FunctionEHFrameInfo *EFI) {
+  //
+  // The code below is a modified/simplified version of EmitExceptionTable
+  //
+
+  // Load saved information from EHFrameInfo
+  const MonoEHFrameInfo *MonoEH = &EFI->MonoEH;
+  const std::vector<const GlobalVariable *> &TypeInfos = MonoEH->TypeInfos;
+  const std::vector<unsigned> &FilterIds = MonoEH->FilterIds;
+  const std::vector<LandingPadInfo> &PadInfos = MonoEH->PadInfos;
+  const std::vector<CallSiteEntry> CallSites = MonoEH->CallSites;
+  int FunctionNumber = MonoEH->FunctionNumber;
+  int FrameReg = MonoEH->FrameReg;
+  int ThisOffset = MonoEH->ThisOffset;
+
+  // Sort the landing pads in order of their type ids.  This is used to fold
+  // duplicate actions.
+  SmallVector<const LandingPadInfo *, 64> LandingPads;
+  LandingPads.reserve(PadInfos.size());
+
+  for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
+    LandingPads.push_back(&PadInfos[i]);
+
+  std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
+
+  // Compute the actions table and gather the first action index for each
+  // landing pad site.
+  SmallVector<ActionEntry, 32> Actions;
+  SmallVector<unsigned, 64> FirstActions;
+  unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions);
+
+  // 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 when using DWARF exception handling.
+  RangeMapType PadMap;
+  for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
+    const LandingPadInfo *LandingPad = LandingPads[i];
+    for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
+      MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
+      assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
+      PadRange P = { i, j };
+      PadMap[BeginLabel] = P;
+    }
+  }
+
+  assert(Asm->MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI);
+
+  // Final tallies.
+
+  // Call sites.
+  
+  unsigned CallSiteTableLength;
+
+  unsigned SiteStartSize  = 4; // dwarf::DW_EH_PE_udata4
+  unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4
+  unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4
+  CallSiteTableLength = 
+    CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize);
+
+  for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
+    CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action);
+  }
+
+  // Type infos.
+  unsigned TTypeEncoding;
+  unsigned TypeFormatSize;
+
+  // The type_info itself is emitted
+  TTypeEncoding = dwarf::DW_EH_PE_udata4;
+  TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding);
+
+  // Emit the LSDA.
+
+  // Emit the LSDA header.
+  if (FrameReg != -1) {
+    // Keep this in sync with JITDwarfEmitter::EmitExceptionTable ()
+    // FIXME: If this method has no clauses, avoid emitting the rest of the info
+    // Mark that this is a mono specific LSDA header using a magic value
+    Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "@LPStart");
+    Asm->EmitULEB128(0x4d4fef4f, "MONO Magic", 0);
+    Asm->EmitULEB128(1, "Version", 0);
+
+    // Emit 'this' location
+    Asm->OutStreamer.AddComment("bregx");
+    Asm->EmitInt8((int)dwarf::DW_OP_bregx);
+    Asm->EmitULEB128(FrameReg, "Base reg");
+    Asm->EmitSLEB128(ThisOffset, "Offset");
+  } else {
+    Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
+  }
+  Asm->EmitEncodingByte(TTypeEncoding, "@TType");
+
+  unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
+  unsigned CallSiteTableLengthSize =
+    MCAsmInfo::getULEB128Size(CallSiteTableLength);
+  unsigned TTypeBaseOffset =
+    sizeof(int8_t) +                            // Call site format
+    CallSiteTableLengthSize +                   // Call site table length size
+    CallSiteTableLength +                       // Call site table length
+    SizeActions +                               // Actions size
+    SizeTypes;
+
+  Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", 0);
+
+  assert(Asm->MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI);
+
+  // The call-site table is a list of all call sites that may throw an
+  // exception (including C++ 'throw' statements) in the procedure
+  // fragment. It immediately follows the LSDA header. Each entry indicates,
+  // for a given call, the first corresponding action record and corresponding
+  // landing pad.
+  //
+  // The table begins with the number of bytes, stored as an LEB128
+  // compressed, unsigned integer. The records immediately follow the record
+  // count. They are sorted in increasing call-site address. Each record
+  // indicates:
+  //
+  //   * The position of the call-site.
+  //   * The position of the landing pad.
+  //   * The first action record for that call site.
+  //
+  // A missing entry in the call-site table indicates that a call is not
+  // supposed to throw.
+
+  // Emit the landing pad call site table.
+  Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
+
+  // Add extra padding if it wasn't added to the TType base offset.
+  Asm->EmitULEB128(CallSiteTableLength, "Call site table length", 0);
+
+  for (std::vector<CallSiteEntry>::const_iterator
+         I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
+    const CallSiteEntry &S = *I;
+      
+    MCSymbol *EHFuncBeginSym =
+      Asm->GetTempSymbol("eh_func_begin", FunctionNumber);
+      
+    MCSymbol *BeginLabel = S.BeginLabel;
+    if (BeginLabel == 0)
+      BeginLabel = EHFuncBeginSym;
+    MCSymbol *EndLabel = S.EndLabel;
+    if (EndLabel == 0)
+      EndLabel = Asm->GetTempSymbol("eh_func_end", FunctionNumber);
+        
+    // Offset of the call site relative to the previous call site, counted in
+    // number of 16-byte bundles. The first call site is counted relative to
+    // the start of the procedure fragment.
+    Asm->OutStreamer.AddComment("Region start");
+    Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
+      
+    Asm->OutStreamer.AddComment("Region length");
+    Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
+
+
+    // Offset of the landing pad, counted in 16-byte bundles relative to the
+    // @LPStart address.
+    Asm->OutStreamer.AddComment("Landing pad");
+    if (!S.PadLabel)
+      Asm->OutStreamer.EmitIntValue(0, 4/*size*/);
+    else
+      Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4);
+
+    // Offset of the first associated action record, relative to the start of
+    // the action table. This value is biased by 1 (1 indicates the start of
+    // the action table), and 0 indicates that there are no actions.
+    Asm->EmitULEB128(S.Action, "Action");
+  }
+
+  // Emit the Action Table.
+  if (Actions.size() != 0) {
+    Asm->OutStreamer.AddComment("-- Action Record Table --");
+    Asm->OutStreamer.AddBlankLine();
+  }
+  
+  for (SmallVectorImpl<ActionEntry>::const_iterator
+         I = Actions.begin(), E = Actions.end(); I != E; ++I) {
+    const ActionEntry &Action = *I;
+    Asm->OutStreamer.AddComment("Action Record");
+    Asm->OutStreamer.AddBlankLine();
+
+    // Type Filter
+    //
+    //   Used by the runtime to match the type of the thrown exception to the
+    //   type of the catch clauses or the types in the exception specification.
+    Asm->EmitSLEB128(Action.ValueForTypeID, "  TypeInfo index");
+
+    // Action Record
+    //
+    //   Self-relative signed displacement in bytes of the next action record,
+    //   or 0 if there is no next action record.
+    Asm->EmitSLEB128(Action.NextAction, "  Next action");
+  }
+
+  // Emit the Catch TypeInfos.
+  if (!TypeInfos.empty()) {
+    Asm->OutStreamer.AddComment("-- Catch TypeInfos --");
+    Asm->OutStreamer.AddBlankLine();
+  }
+  for (std::vector<const GlobalVariable *>::const_reverse_iterator
+         I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) {
+    const GlobalVariable *GV = *I;
+
+    //
+    // Mono typeinfos are simple constant integers. Emit the constant itself.
+    //
+    assert(GV);
+    const ConstantInt *ci = dyn_cast<ConstantInt>(GV->getInitializer());
+
+    Asm->OutStreamer.AddComment("TypeInfo");
+    Asm->OutStreamer.EmitIntValue(ci->getZExtValue(),Asm->GetSizeOfEncodedValue(TTypeEncoding));
+  }
+
+  // Emit the Exception Specifications.
+  if (!FilterIds.empty()) {
+    Asm->OutStreamer.AddComment("-- Filter IDs --");
+    Asm->OutStreamer.AddBlankLine();
+  }
+  for (std::vector<unsigned>::const_iterator
+         I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
+    unsigned TypeID = *I;
+    Asm->EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0);
+  }
+}
+
+// EmitMonoEHFrame - Emit Mono specific exception handling tables
+void DwarfMonoException::EmitMonoEHFrame(const Function *Personality)
+{
+  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+
+  unsigned FuncAddrEncoding = TLOF.getMonoEHTableEncoding ();
+
+  // Size and sign of stack growth.
+  int stackGrowth = Asm->getDataLayout().getPointerSize();
+  if (Asm->TM.getFrameLowering()->getStackGrowthDirection() ==
+      TargetFrameLowering::StackGrowsDown)
+    stackGrowth *= -1;
+
+  MCStreamer& Streamer = Asm->OutStreamer;
+
+  //
+  // The Mono runtime obtains EH info for LLVM JITted code by decoding the GNU EH frame
+  // created by LLVM. For static compilation, this has certain problems:
+  // - .eh_frame resides in a different segment, which makes it impossible to read it at
+  // runtime on some platforms, like the iphone
+  // - the iphone linker can't generate .eh_frame_hdr
+  // - the table is very verbose, a single FDE is about 20-24 bytes on arm, negating any
+  // code size gains obtained by using LLVM.
+  // - the information is spread across three data structures: the eh_frame, the LSDA and
+  //   type_info, which are potentially in different sections/segments, leading to relocation/
+  //   linking problems.
+  // An alternative would be using the official ARM EH tables. This has problems too:
+  // - it is also in a separate section
+  // - it is very badly specified
+  // - it needs GNU assembler/linker support to work.
+  //
+  // To solve these problems, we generate our own custom EH tables:
+  // - the table is in the rodata segment, pointed to by a local symbol.
+  // - it contains an .eh_frame_hdr style lookup table.
+  // - the LSDA and type_info are embedded into the FDE entries.
+  //
+  // http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html
+  //
+  // It is hard to get smaller tables without assembler support, since we can't encode
+  // offsets in less that 4 bytes, can't encode information into the upper bits of offsets etc.
+  //
+
+  // Can't use rodata as the symbols we reference are in the text segment
+  Streamer.SwitchSection(TLOF.getTextSection());
+
+  MCSymbol *EHFrameHdrSym =
+	  Asm->OutContext.GetOrCreateSymbol(Twine("mono_eh_frame"));
+  MCSymbol *EHFrameEndSym = Asm->GetTempSymbol ("mono_eh_frame_end");
+
+  Asm->EmitAlignment(4);
+  Streamer.EmitLabel(EHFrameHdrSym);
+  const MCExpr *Length = MakeStartMinusEndExpr(Streamer, *EHFrameHdrSym,
+                                               *EHFrameEndSym, 0);
+  if (Asm->MAI->hasDotTypeDotSizeDirective()) {
+    Streamer.EmitELFSize(EHFrameHdrSym, Length);
+    Streamer.EmitSymbolAttribute(EHFrameHdrSym, MCSA_ELF_TypeObject);
+  }
+
+  // Header
+
+  Streamer.AddComment("version");
+  Asm->OutStreamer.EmitIntValue(3, 1);
+  Asm->OutStreamer.AddComment ("func addr encoding");
+  Asm->OutStreamer.EmitIntValue (FuncAddrEncoding, 1);
+
+  // Search table
+  Asm->EmitAlignment(2);
+  Streamer.AddComment("fde_count");
+  Streamer.EmitIntValue (EHFrames.size(), 4);
+  for (std::vector<FunctionEHFrameInfo>::iterator
+		   I = EHFrames.begin(), E = EHFrames.end(); I != E; ++I) {
+	  const FunctionEHFrameInfo &EHFrameInfo = *I;
+
+      //
+      // Instead of the function address, we emit the mono method index, which is easier to encode.
+      //
+      Streamer.AddComment("mono method idx");
+      Streamer.EmitIntValue (EHFrameInfo.MonoEH.MonoMethodIdx, 4);
+	  MCSymbol *FDEBeginSym = Asm->GetTempSymbol ("mono_eh_func_begin", EHFrameInfo.Number);
+	  Asm->EmitLabelDifference(FDEBeginSym, EHFrameHdrSym, 4);
+  }
+  // Emit a last entry to simplify binary searches and to enable the computation of
+  // the size of the last function/FDE entry
+  if (EHFrames.size() == 0) {
+	  Streamer.EmitIntValue (-1, 4);
+	  Asm->EmitLabelDifference(EHFrameHdrSym, EHFrameHdrSym, 4);
+  } else {
+	  // Emit the size of the last function, since it cannot be computed using the next table entry
+	  MCSymbol *Sym1 = Asm->GetTempSymbol("eh_func_begin", EHFrames.size() - 1);
+	  MCSymbol *Sym2 = Asm->GetTempSymbol("eh_func_end", EHFrames.size() - 1);
+	  Asm->EmitLabelDifference(Sym2, Sym1, 4);
+	  MCSymbol *Sym3 = Asm->GetTempSymbol ("mono_eh_frame_end");
+	  Asm->EmitLabelDifference(Sym3, EHFrameHdrSym, 4);
+  }
+
+  // CIE
+  // This comes right after the search table
+  Asm->EmitULEB128(1, "CIE Code Alignment Factor");
+  Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
+  Streamer.AddComment("CIE Return Address Column");
+  const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
+  Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true));
+
+  Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "Personality");
+
+  int CFAOffset = 0;
+
+  int dataAlignmentFactor = stackGrowth;
+
+  // Initial CIE program
+  EmitCFIInstructions(Streamer, Streamer.getContext().getAsmInfo()->getInitialFrameState(), NULL, CFAOffset, dataAlignmentFactor);
+
+  int CIECFAOffset = CFAOffset;
+
+  // FDEs
+  Streamer.AddBlankLine();
+  for (std::vector<FunctionEHFrameInfo>::iterator
+		   I = EHFrames.begin(), E = EHFrames.end(); I != E; ++I) {
+	  const FunctionEHFrameInfo &EHFrameInfo = *I;
+      int Index = EHFrameInfo.Number;
+
+	  MCSymbol *FDEBeginSym = Asm->GetTempSymbol ("mono_eh_func_begin", Index);
+      Streamer.EmitLabel(FDEBeginSym);
+
+      // No need for length, CIE, PC begin, PC range, alignment
+
+      // Emit augmentation
+      if (EHFrameInfo.hasLandingPads) {
+        // Need an extra has_augmentation field as the augmentation size is always encoded
+        // in 4 bytes
+        Asm->EmitULEB128(1, "Has augmentation");
+
+        Streamer.AddComment("Augmentation size");
+        Asm->EmitLabelDifference(Asm->GetTempSymbol("mono_fde_aug_end", Index),
+                                 Asm->GetTempSymbol("mono_fde_aug_begin", Index),
+                                 4);
+
+        Streamer.EmitLabel(Asm->GetTempSymbol("mono_fde_aug_begin", Index));
+        EmitMonoLSDA (&EHFrameInfo);
+        Streamer.EmitLabel(Asm->GetTempSymbol("mono_fde_aug_end", Index));
+      } else {
+        Asm->EmitULEB128(0, "Has augmentation");
+      }
+
+      CFAOffset = CIECFAOffset;
+
+      EmitCFIInstructions(Streamer, EHFrameInfo.Instructions, NULL, CFAOffset, dataAlignmentFactor);
+
+      Streamer.AddBlankLine();
+  }
+
+  Streamer.EmitLabel(EHFrameEndSym);
+}
+
+DwarfMonoException::DwarfMonoException(AsmPrinter *A)
+  : DwarfException(A) {}
+
+DwarfMonoException::~DwarfMonoException() {}
+
+void DwarfMonoException::BeginFunction(const MachineFunction *MF)
+{
+  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin",
+                                                Asm->getFunctionNumber()));
+}
+
+void DwarfMonoException::EndFunction() {
+  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end",
+                                                Asm->getFunctionNumber()));
+
+  MMI->TidyLandingPads();
+
+  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+  MCSymbol *FunctionEHSym =
+    Asm->GetSymbolWithGlobalValueBase(Asm->MF->getFunction(), ".eh",
+                                      TLOF.isFunctionEHFrameSymbolPrivate());
+
+  // Save EH frame information
+  FunctionEHFrameInfo EHFrameInfo =
+    FunctionEHFrameInfo(FunctionEHSym,
+                        Asm->getFunctionNumber(),
+                        MMI->getPersonalityIndex(),
+                        Asm->MF->getFrameInfo()->adjustsStack(),
+                        !MMI->getLandingPads().empty(),
+                        MMI->getFrameInstructions(),
+                        Asm->MF->getFunction());
+
+  PrepareMonoLSDA(&EHFrameInfo);
+
+  EHFrames.push_back(EHFrameInfo);
+}
+
+void DwarfMonoException::EndModule() {
+  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+
+  // Emit references to all used personality functions
+  const std::vector<const Function*> &Personalities = MMI->getPersonalities();
+  for (size_t i = 0, e = Personalities.size(); i != e; ++i) {
+    if (!Personalities[i])
+      continue;
+    MCSymbol *Sym = Asm->Mang->getSymbol(Personalities[i]);
+    TLOF.emitPersonalityValue(Asm->OutStreamer, Asm->TM, Sym);
+  }
+
+  EmitMonoEHFrame(Personalities[0]);
+}

Modified: lib/CodeGen/MachineFunction.cpp
===================================================================
@@ -25,6 +25,7 @@
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MonoMachineFunctionInfo.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/DebugInfo.h"
 #include "llvm/IR/DataLayout.h"
@@ -60,6 +61,7 @@
     RegInfo = 0;
 
   MFInfo = 0;
+  MonoInfo = 0;
   FrameInfo =
     new (Allocator) MachineFrameInfo(TM,!F->hasFnAttribute("no-realign-stack"));
 
@@ -69,6 +71,7 @@
                                 getStackAlignment(AttributeSet::FunctionIndex));
 
   ConstantPool = new (Allocator) MachineConstantPool(TM);
+  MonoInfo = new (Allocator) MonoMachineFunctionInfo(*this);
   Alignment = TM.getTargetLowering()->getMinFunctionAlignment();
 
   // FIXME: Shouldn't use pref alignment if explicit alignment is set on Fn.
@@ -100,6 +103,10 @@
     MFInfo->~MachineFunctionInfo();
     Allocator.Deallocate(MFInfo);
   }
+  if (MonoInfo) {
+    MonoInfo->~MonoMachineFunctionInfo();
+    Allocator.Deallocate(MonoInfo);
+  }
 
   FrameInfo->~MachineFrameInfo();
   Allocator.Deallocate(FrameInfo);

Modified: lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
===================================================================
@@ -21,6 +21,7 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MonoMachineFunctionInfo.h"
 #include "llvm/DebugInfo.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
@@ -95,6 +96,19 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) {
         StaticAllocaMap[AI] =
           MF->getFrameInfo()->CreateStackObject(TySize, Align, false,
                                                 MayNeedSP, AI);
+
+        //
+        // The mono exception handling code needs to location of the 'this' pointer
+        // to handle stack traces containing generic shared methods.
+        // To implement this, it saves the this pointer to an alloca which is marked with
+        // the 'mono.this' custom metadata. We save the stack slot used by this alloca
+        // in MachineFunction, so the dwarf exception info emission code can use it to
+        // compute the reg+offset for it, and save it into the LSDA.
+        //
+        if (AI->getMetadata("mono.this")) {
+          MonoMachineFunctionInfo *MonoFI = MF->getMonoInfo();
+          MonoFI->setThisStackSlot (StaticAllocaMap[AI]);
+        }
       }
 
   for (; BB != EB; ++BB)

Modified: lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
===================================================================
@@ -18,13 +18,16 @@
 #include "llvm/CodeGen/JITCodeEmitter.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MonoMachineFunctionInfo.h"
 #include "llvm/ExecutionEngine/JITMemoryManager.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/Function.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetFrameLowering.h"
 #include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
@@ -201,7 +204,10 @@ unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF,
   const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
   const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
-  if (PadInfos.empty()) return 0;
+
+  int ThisSlot = MF->getMonoInfo()->getThisStackSlot();
+
+  if (PadInfos.empty() && ThisSlot == -1) return 0;
 
   // Sort the landing pads in order of their type ids.  This is used to fold
   // duplicate actions.
@@ -388,8 +394,25 @@ unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF,
   unsigned char* DwarfExceptionTable = (unsigned char*)JCE->getCurrentPCValue();
 
   // Emit the header.
-  JCE->emitByte(dwarf::DW_EH_PE_omit);
-  // Asm->EOL("LPStart format (DW_EH_PE_omit)");
+
+  if (ThisSlot != -1) {
+    // Keep this in sync with DwarfException::EmitExceptionTable ()
+    JCE->emitByte(dwarf::DW_EH_PE_udata4);
+    JCE->emitULEB128Bytes(0x4d4fef4f);
+    JCE->emitULEB128Bytes(1);
+
+    // Emit 'this' location
+    unsigned FrameReg;
+    int Offset = MF->getTarget ().getFrameLowering ()->getFrameIndexReference (*MF, ThisSlot, FrameReg);
+    FrameReg = MF->getTarget ().getRegisterInfo ()->getDwarfRegNum (FrameReg, true);
+
+    JCE->emitByte((int)dwarf::DW_OP_bregx);
+    JCE->emitULEB128Bytes(FrameReg);
+    JCE->emitSLEB128Bytes(Offset);
+  } else {
+    JCE->emitByte(dwarf::DW_EH_PE_omit);
+    // Asm->EOL("LPStart format (DW_EH_PE_omit)");
+  }
   JCE->emitByte(dwarf::DW_EH_PE_absptr);
   // Asm->EOL("TType format (DW_EH_PE_absptr)");
   JCE->emitULEB128Bytes(TypeOffset);
@@ -550,16 +573,16 @@ unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF,
 
   // If there is a personality and landing pads then point to the language
   // specific data area in the exception table.
-  if (Personality) {
+  if (ExceptionTable) {
     JCE->emitULEB128Bytes(PointerSize == 4 ? 4 : 8);
 
     if (PointerSize == 4) {
-      if (!MMI->getLandingPads().empty())
+      if (ExceptionTable)
         JCE->emitInt32(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue());
       else
         JCE->emitInt32((int)0);
     } else {
-      if (!MMI->getLandingPads().empty())
+      if (ExceptionTable)
         JCE->emitInt64(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue());
       else
         JCE->emitInt64((int)0);

Modified: lib/MC/MCObjectFileInfo.cpp
===================================================================
@@ -27,6 +27,11 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) {
   TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
     dwarf::DW_EH_PE_sdata4;
 
+  if (T.getOS() == Triple::IOS)
+    MonoEHTableEncoding = dwarf::DW_EH_PE_absptr;
+  else
+    MonoEHTableEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+
   // .comm doesn't support alignment before Leopard.
   if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5))
     CommDirectiveSupportsAlignment = false;
@@ -323,6 +328,11 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
       FDEEncoding = dwarf::DW_EH_PE_absptr;
       TTypeEncoding = dwarf::DW_EH_PE_absptr;
     }
+  } else if (T.getArch() == Triple::arm) {
+    PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+    LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+    FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
+    TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
   }
 
   // Solaris requires different flags for .eh_frame to seemingly every other
@@ -336,6 +346,7 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
       EHSectionFlags |= ELF::SHF_WRITE;
   }
 
+  MonoEHTableEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
 
   // ELF
   BSSSection =

Modified: lib/Transforms/Scalar/GlobalMerge.cpp
===================================================================
@@ -266,6 +266,8 @@ bool GlobalMerge::doInitialization(Module &M) {
     if (isMustKeepGlobalVariable(I))
       continue;
 
+    // FIXME: This merges Mono's type_info globals, breaking EH
+/*
     if (TD->getTypeAllocSize(Ty) < MaxOffset) {
       if (TargetLoweringObjectFile::getKindForGlobal(I, TLI->getTargetMachine())
           .isBSSLocal())
@@ -275,6 +277,7 @@ bool GlobalMerge::doInitialization(Module &M) {
       else
         Globals[AddressSpace].push_back(I);
     }
+*/
   }
 
   for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator


_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches