1193323Sed//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10198090Srdivacky// This file contains support for writing DWARF exception info into asm files.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#include "DwarfException.h"
15252723Sdim#include "llvm/ADT/SmallString.h"
16252723Sdim#include "llvm/ADT/StringExtras.h"
17252723Sdim#include "llvm/ADT/Twine.h"
18206274Srdivacky#include "llvm/CodeGen/AsmPrinter.h"
19193323Sed#include "llvm/CodeGen/MachineFrameInfo.h"
20198090Srdivacky#include "llvm/CodeGen/MachineFunction.h"
21252723Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
22252723Sdim#include "llvm/IR/DataLayout.h"
23252723Sdim#include "llvm/IR/Module.h"
24198090Srdivacky#include "llvm/MC/MCAsmInfo.h"
25198090Srdivacky#include "llvm/MC/MCContext.h"
26198090Srdivacky#include "llvm/MC/MCExpr.h"
27198090Srdivacky#include "llvm/MC/MCSection.h"
28198090Srdivacky#include "llvm/MC/MCStreamer.h"
29202878Srdivacky#include "llvm/MC/MCSymbol.h"
30252723Sdim#include "llvm/Support/Dwarf.h"
31252723Sdim#include "llvm/Support/ErrorHandling.h"
32252723Sdim#include "llvm/Support/FormattedStream.h"
33202878Srdivacky#include "llvm/Target/Mangler.h"
34218893Sdim#include "llvm/Target/TargetFrameLowering.h"
35198090Srdivacky#include "llvm/Target/TargetLoweringObjectFile.h"
36198090Srdivacky#include "llvm/Target/TargetOptions.h"
37198090Srdivacky#include "llvm/Target/TargetRegisterInfo.h"
38193323Sedusing namespace llvm;
39193323Sed
40206274SrdivackyDwarfException::DwarfException(AsmPrinter *A)
41218893Sdim  : Asm(A), MMI(Asm->MMI) {}
42193323Sed
43207618SrdivackyDwarfException::~DwarfException() {}
44193323Sed
45193323Sed/// SharedTypeIds - How many leading type ids two landing pads have in common.
46193323Sedunsigned DwarfException::SharedTypeIds(const LandingPadInfo *L,
47193323Sed                                       const LandingPadInfo *R) {
48193323Sed  const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
49193323Sed  unsigned LSize = LIds.size(), RSize = RIds.size();
50193323Sed  unsigned MinSize = LSize < RSize ? LSize : RSize;
51193323Sed  unsigned Count = 0;
52193323Sed
53193323Sed  for (; Count != MinSize; ++Count)
54193323Sed    if (LIds[Count] != RIds[Count])
55193323Sed      return Count;
56193323Sed
57193323Sed  return Count;
58193323Sed}
59193323Sed
60193323Sed/// PadLT - Order landing pads lexicographically by type id.
61193323Sedbool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) {
62193323Sed  const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
63193323Sed  unsigned LSize = LIds.size(), RSize = RIds.size();
64193323Sed  unsigned MinSize = LSize < RSize ? LSize : RSize;
65193323Sed
66193323Sed  for (unsigned i = 0; i != MinSize; ++i)
67193323Sed    if (LIds[i] != RIds[i])
68193323Sed      return LIds[i] < RIds[i];
69193323Sed
70193323Sed  return LSize < RSize;
71193323Sed}
72193323Sed
73198090Srdivacky/// ComputeActionsTable - Compute the actions table and gather the first action
74198090Srdivacky/// index for each landing pad site.
75198090Srdivackyunsigned DwarfException::
76198090SrdivackyComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
77198090Srdivacky                    SmallVectorImpl<ActionEntry> &Actions,
78198090Srdivacky                    SmallVectorImpl<unsigned> &FirstActions) {
79193323Sed
80198090Srdivacky  // The action table follows the call-site table in the LSDA. The individual
81198090Srdivacky  // records are of two types:
82198090Srdivacky  //
83198090Srdivacky  //   * Catch clause
84198090Srdivacky  //   * Exception specification
85198090Srdivacky  //
86198090Srdivacky  // The two record kinds have the same format, with only small differences.
87198090Srdivacky  // They are distinguished by the "switch value" field: Catch clauses
88198090Srdivacky  // (TypeInfos) have strictly positive switch values, and exception
89198090Srdivacky  // specifications (FilterIds) have strictly negative switch values. Value 0
90198090Srdivacky  // indicates a catch-all clause.
91198090Srdivacky  //
92198090Srdivacky  // Negative type IDs index into FilterIds. Positive type IDs index into
93198090Srdivacky  // TypeInfos.  The value written for a positive type ID is just the type ID
94198090Srdivacky  // itself.  For a negative type ID, however, the value written is the
95193323Sed  // (negative) byte offset of the corresponding FilterIds entry.  The byte
96198090Srdivacky  // offset is usually equal to the type ID (because the FilterIds entries are
97198090Srdivacky  // written using a variable width encoding, which outputs one byte per entry
98198090Srdivacky  // as long as the value written is not too large) but can differ.  This kind
99198090Srdivacky  // of complication does not occur for positive type IDs because type infos are
100193323Sed  // output using a fixed width encoding.  FilterOffsets[i] holds the byte
101193323Sed  // offset corresponding to FilterIds[i].
102198090Srdivacky
103198090Srdivacky  const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
104193323Sed  SmallVector<int, 16> FilterOffsets;
105193323Sed  FilterOffsets.reserve(FilterIds.size());
106193323Sed  int Offset = -1;
107198090Srdivacky
108198090Srdivacky  for (std::vector<unsigned>::const_iterator
109198090Srdivacky         I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) {
110193323Sed    FilterOffsets.push_back(Offset);
111198090Srdivacky    Offset -= MCAsmInfo::getULEB128Size(*I);
112193323Sed  }
113193323Sed
114193323Sed  FirstActions.reserve(LandingPads.size());
115193323Sed
116193323Sed  int FirstAction = 0;
117193323Sed  unsigned SizeActions = 0;
118198090Srdivacky  const LandingPadInfo *PrevLPI = 0;
119198090Srdivacky
120198090Srdivacky  for (SmallVectorImpl<const LandingPadInfo *>::const_iterator
121198090Srdivacky         I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) {
122198090Srdivacky    const LandingPadInfo *LPI = *I;
123198090Srdivacky    const std::vector<int> &TypeIds = LPI->TypeIds;
124206274Srdivacky    unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0;
125193323Sed    unsigned SizeSiteActions = 0;
126193323Sed
127193323Sed    if (NumShared < TypeIds.size()) {
128193323Sed      unsigned SizeAction = 0;
129203954Srdivacky      unsigned PrevAction = (unsigned)-1;
130193323Sed
131193323Sed      if (NumShared) {
132206274Srdivacky        unsigned SizePrevIds = PrevLPI->TypeIds.size();
133193323Sed        assert(Actions.size());
134203954Srdivacky        PrevAction = Actions.size() - 1;
135203954Srdivacky        SizeAction =
136203954Srdivacky          MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) +
137203954Srdivacky          MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID);
138193323Sed
139193323Sed        for (unsigned j = NumShared; j != SizePrevIds; ++j) {
140203954Srdivacky          assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!");
141193323Sed          SizeAction -=
142203954Srdivacky            MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID);
143203954Srdivacky          SizeAction += -Actions[PrevAction].NextAction;
144203954Srdivacky          PrevAction = Actions[PrevAction].Previous;
145193323Sed        }
146193323Sed      }
147193323Sed
148193323Sed      // Compute the actions.
149198090Srdivacky      for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) {
150198090Srdivacky        int TypeID = TypeIds[J];
151198090Srdivacky        assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
152193323Sed        int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
153198090Srdivacky        unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID);
154193323Sed
155193323Sed        int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
156198090Srdivacky        SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction);
157193323Sed        SizeSiteActions += SizeAction;
158193323Sed
159198090Srdivacky        ActionEntry Action = { ValueForTypeID, NextAction, PrevAction };
160193323Sed        Actions.push_back(Action);
161203954Srdivacky        PrevAction = Actions.size() - 1;
162193323Sed      }
163193323Sed
164193323Sed      // Record the first action of the landing pad site.
165193323Sed      FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
166193323Sed    } // else identical - re-use previous FirstAction
167193323Sed
168198090Srdivacky    // Information used when created the call-site table. The action record
169198090Srdivacky    // field of the call site record is the offset of the first associated
170198090Srdivacky    // action record, relative to the start of the actions table. This value is
171203954Srdivacky    // biased by 1 (1 indicating the start of the actions table), and 0
172198090Srdivacky    // indicates that there are no actions.
173193323Sed    FirstActions.push_back(FirstAction);
174193323Sed
175193323Sed    // Compute this sites contribution to size.
176193323Sed    SizeActions += SizeSiteActions;
177198090Srdivacky
178198090Srdivacky    PrevLPI = LPI;
179193323Sed  }
180193323Sed
181198090Srdivacky  return SizeActions;
182198090Srdivacky}
183193323Sed
184199481Srdivacky/// CallToNoUnwindFunction - Return `true' if this is a call to a function
185199481Srdivacky/// marked `nounwind'. Return `false' otherwise.
186199481Srdivackybool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) {
187235633Sdim  assert(MI->isCall() && "This should be a call instruction!");
188199481Srdivacky
189199481Srdivacky  bool MarkedNoUnwind = false;
190199481Srdivacky  bool SawFunc = false;
191199481Srdivacky
192199481Srdivacky  for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
193199481Srdivacky    const MachineOperand &MO = MI->getOperand(I);
194199481Srdivacky
195206083Srdivacky    if (!MO.isGlobal()) continue;
196218893Sdim
197207618Srdivacky    const Function *F = dyn_cast<Function>(MO.getGlobal());
198206083Srdivacky    if (F == 0) continue;
199199481Srdivacky
200206083Srdivacky    if (SawFunc) {
201206083Srdivacky      // Be conservative. If we have more than one function operand for this
202206083Srdivacky      // call, then we can't make the assumption that it's the callee and
203206083Srdivacky      // not a parameter to the call.
204218893Sdim      //
205206083Srdivacky      // FIXME: Determine if there's a way to say that `F' is the callee or
206206083Srdivacky      // parameter.
207206083Srdivacky      MarkedNoUnwind = false;
208206083Srdivacky      break;
209199481Srdivacky    }
210206083Srdivacky
211206083Srdivacky    MarkedNoUnwind = F->doesNotThrow();
212206083Srdivacky    SawFunc = true;
213199481Srdivacky  }
214199481Srdivacky
215199481Srdivacky  return MarkedNoUnwind;
216199481Srdivacky}
217199481Srdivacky
218198090Srdivacky/// ComputeCallSiteTable - Compute the call-site table.  The entry for an invoke
219198090Srdivacky/// has a try-range containing the call, a non-zero landing pad, and an
220198090Srdivacky/// appropriate action.  The entry for an ordinary call has a try-range
221198090Srdivacky/// containing the call and zero for the landing pad and the action.  Calls
222198090Srdivacky/// marked 'nounwind' have no entry and must not be contained in the try-range
223198090Srdivacky/// of any entry - they form gaps in the table.  Entries must be ordered by
224198090Srdivacky/// try-range address.
225198090Srdivackyvoid DwarfException::
226198090SrdivackyComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
227198090Srdivacky                     const RangeMapType &PadMap,
228198090Srdivacky                     const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
229198090Srdivacky                     const SmallVectorImpl<unsigned> &FirstActions) {
230193323Sed  // The end label of the previous invoke or nounwind try-range.
231205218Srdivacky  MCSymbol *LastLabel = 0;
232193323Sed
233193323Sed  // Whether there is a potentially throwing instruction (currently this means
234193323Sed  // an ordinary call) between the end of the previous try-range and now.
235193323Sed  bool SawPotentiallyThrowing = false;
236193323Sed
237198090Srdivacky  // Whether the last CallSite entry was for an invoke.
238193323Sed  bool PreviousIsInvoke = false;
239193323Sed
240193323Sed  // Visit all instructions in order of address.
241206274Srdivacky  for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end();
242193323Sed       I != E; ++I) {
243193323Sed    for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
244193323Sed         MI != E; ++MI) {
245193323Sed      if (!MI->isLabel()) {
246235633Sdim        if (MI->isCall())
247199481Srdivacky          SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI);
248193323Sed        continue;
249193323Sed      }
250193323Sed
251193323Sed      // End of the previous try-range?
252205218Srdivacky      MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol();
253193323Sed      if (BeginLabel == LastLabel)
254193323Sed        SawPotentiallyThrowing = false;
255193323Sed
256193323Sed      // Beginning of a new try-range?
257199481Srdivacky      RangeMapType::const_iterator L = PadMap.find(BeginLabel);
258193323Sed      if (L == PadMap.end())
259193323Sed        // Nope, it was just some random label.
260193323Sed        continue;
261193323Sed
262198090Srdivacky      const PadRange &P = L->second;
263193323Sed      const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
264193323Sed      assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
265193323Sed             "Inconsistent landing pad map!");
266193323Sed
267198090Srdivacky      // For Dwarf exception handling (SjLj handling doesn't use this). If some
268198090Srdivacky      // instruction between the previous try-range and this one may throw,
269198090Srdivacky      // create a call-site entry with no landing pad for the region between the
270198090Srdivacky      // try-ranges.
271218893Sdim      if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) {
272198090Srdivacky        CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 };
273193323Sed        CallSites.push_back(Site);
274193323Sed        PreviousIsInvoke = false;
275193323Sed      }
276193323Sed
277193323Sed      LastLabel = LandingPad->EndLabels[P.RangeIndex];
278193323Sed      assert(BeginLabel && LastLabel && "Invalid landing pad!");
279193323Sed
280206083Srdivacky      if (!LandingPad->LandingPadLabel) {
281206083Srdivacky        // Create a gap.
282206083Srdivacky        PreviousIsInvoke = false;
283206083Srdivacky      } else {
284193323Sed        // This try-range is for an invoke.
285198090Srdivacky        CallSiteEntry Site = {
286198090Srdivacky          BeginLabel,
287198090Srdivacky          LastLabel,
288198090Srdivacky          LandingPad->LandingPadLabel,
289198090Srdivacky          FirstActions[P.PadIndex]
290198090Srdivacky        };
291193323Sed
292198090Srdivacky        // Try to merge with the previous call-site. SJLJ doesn't do this
293218893Sdim        if (PreviousIsInvoke && Asm->MAI->isExceptionHandlingDwarf()) {
294193323Sed          CallSiteEntry &Prev = CallSites.back();
295193323Sed          if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
296193323Sed            // Extend the range of the previous entry.
297193323Sed            Prev.EndLabel = Site.EndLabel;
298193323Sed            continue;
299193323Sed          }
300193323Sed        }
301193323Sed
302193323Sed        // Otherwise, create a new call-site.
303218893Sdim        if (Asm->MAI->isExceptionHandlingDwarf())
304203954Srdivacky          CallSites.push_back(Site);
305203954Srdivacky        else {
306203954Srdivacky          // SjLj EH must maintain the call sites in the order assigned
307203954Srdivacky          // to them by the SjLjPrepare pass.
308203954Srdivacky          unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel);
309203954Srdivacky          if (CallSites.size() < SiteNo)
310203954Srdivacky            CallSites.resize(SiteNo);
311203954Srdivacky          CallSites[SiteNo - 1] = Site;
312203954Srdivacky        }
313193323Sed        PreviousIsInvoke = true;
314193323Sed      }
315193323Sed    }
316193323Sed  }
317193323Sed
318193323Sed  // If some instruction between the previous try-range and the end of the
319193323Sed  // function may throw, create a call-site entry with no landing pad for the
320193323Sed  // region following the try-range.
321218893Sdim  if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) {
322198090Srdivacky    CallSiteEntry Site = { LastLabel, 0, 0, 0 };
323193323Sed    CallSites.push_back(Site);
324193323Sed  }
325198090Srdivacky}
326193323Sed
327198090Srdivacky/// EmitExceptionTable - Emit landing pads and actions.
328198090Srdivacky///
329198090Srdivacky/// The general organization of the table is complex, but the basic concepts are
330198090Srdivacky/// easy.  First there is a header which describes the location and organization
331198090Srdivacky/// of the three components that follow.
332198090Srdivacky///
333198090Srdivacky///  1. The landing pad site information describes the range of code covered by
334198090Srdivacky///     the try.  In our case it's an accumulation of the ranges covered by the
335198090Srdivacky///     invokes in the try.  There is also a reference to the landing pad that
336198090Srdivacky///     handles the exception once processed.  Finally an index into the actions
337198090Srdivacky///     table.
338198090Srdivacky///  2. The action table, in our case, is composed of pairs of type IDs and next
339198090Srdivacky///     action offset.  Starting with the action index from the landing pad
340198090Srdivacky///     site, each type ID is checked for a match to the current exception.  If
341198090Srdivacky///     it matches then the exception and type id are passed on to the landing
342198090Srdivacky///     pad.  Otherwise the next action is looked up.  This chain is terminated
343198090Srdivacky///     with a next action of zero.  If no type id is found then the frame is
344198090Srdivacky///     unwound and handling continues.
345198090Srdivacky///  3. Type ID table contains references to all the C++ typeinfo for all
346198090Srdivacky///     catches in the function.  This tables is reverse indexed base 1.
347198090Srdivackyvoid DwarfException::EmitExceptionTable() {
348207618Srdivacky  const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
349198090Srdivacky  const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
350198090Srdivacky  const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
351198090Srdivacky
352198090Srdivacky  // Sort the landing pads in order of their type ids.  This is used to fold
353198090Srdivacky  // duplicate actions.
354198090Srdivacky  SmallVector<const LandingPadInfo *, 64> LandingPads;
355198090Srdivacky  LandingPads.reserve(PadInfos.size());
356198090Srdivacky
357198090Srdivacky  for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
358198090Srdivacky    LandingPads.push_back(&PadInfos[i]);
359198090Srdivacky
360198090Srdivacky  std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
361198090Srdivacky
362198090Srdivacky  // Compute the actions table and gather the first action index for each
363198090Srdivacky  // landing pad site.
364198090Srdivacky  SmallVector<ActionEntry, 32> Actions;
365198090Srdivacky  SmallVector<unsigned, 64> FirstActions;
366203954Srdivacky  unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions);
367198090Srdivacky
368198090Srdivacky  // Invokes and nounwind calls have entries in PadMap (due to being bracketed
369198090Srdivacky  // by try-range labels when lowered).  Ordinary calls do not, so appropriate
370198090Srdivacky  // try-ranges for them need be deduced when using DWARF exception handling.
371198090Srdivacky  RangeMapType PadMap;
372198090Srdivacky  for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
373198090Srdivacky    const LandingPadInfo *LandingPad = LandingPads[i];
374198090Srdivacky    for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
375205218Srdivacky      MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
376198090Srdivacky      assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
377198090Srdivacky      PadRange P = { i, j };
378198090Srdivacky      PadMap[BeginLabel] = P;
379198090Srdivacky    }
380198090Srdivacky  }
381198090Srdivacky
382198090Srdivacky  // Compute the call-site table.
383198090Srdivacky  SmallVector<CallSiteEntry, 64> CallSites;
384198090Srdivacky  ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions);
385198090Srdivacky
386193323Sed  // Final tallies.
387193323Sed
388193323Sed  // Call sites.
389206274Srdivacky  bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
390198090Srdivacky  bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true;
391218893Sdim
392204642Srdivacky  unsigned CallSiteTableLength;
393198090Srdivacky  if (IsSJLJ)
394204642Srdivacky    CallSiteTableLength = 0;
395206274Srdivacky  else {
396206274Srdivacky    unsigned SiteStartSize  = 4; // dwarf::DW_EH_PE_udata4
397206274Srdivacky    unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4
398206274Srdivacky    unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4
399218893Sdim    CallSiteTableLength =
400206274Srdivacky      CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize);
401206274Srdivacky  }
402198090Srdivacky
403198090Srdivacky  for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
404204642Srdivacky    CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action);
405198090Srdivacky    if (IsSJLJ)
406204642Srdivacky      CallSiteTableLength += MCAsmInfo::getULEB128Size(i);
407198090Srdivacky  }
408198090Srdivacky
409193323Sed  // Type infos.
410198090Srdivacky  const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection();
411203954Srdivacky  unsigned TTypeEncoding;
412198090Srdivacky  unsigned TypeFormatSize;
413193323Sed
414198090Srdivacky  if (!HaveTTData) {
415198090Srdivacky    // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say
416198090Srdivacky    // that we're omitting that bit.
417203954Srdivacky    TTypeEncoding = dwarf::DW_EH_PE_omit;
418206274Srdivacky    // dwarf::DW_EH_PE_absptr
419245431Sdim    TypeFormatSize = Asm->getDataLayout().getPointerSize();
420198090Srdivacky  } else {
421198090Srdivacky    // Okay, we have actual filters or typeinfos to emit.  As such, we need to
422198090Srdivacky    // pick a type encoding for them.  We're about to emit a list of pointers to
423198090Srdivacky    // typeinfo objects at the end of the LSDA.  However, unless we're in static
424198090Srdivacky    // mode, this reference will require a relocation by the dynamic linker.
425198090Srdivacky    //
426198090Srdivacky    // Because of this, we have a couple of options:
427218893Sdim    //
428198090Srdivacky    //   1) If we are in -static mode, we can always use an absolute reference
429198090Srdivacky    //      from the LSDA, because the static linker will resolve it.
430218893Sdim    //
431198090Srdivacky    //   2) Otherwise, if the LSDA section is writable, we can output the direct
432198090Srdivacky    //      reference to the typeinfo and allow the dynamic linker to relocate
433198090Srdivacky    //      it.  Since it is in a writable section, the dynamic linker won't
434198090Srdivacky    //      have a problem.
435218893Sdim    //
436198090Srdivacky    //   3) Finally, if we're in PIC mode and the LDSA section isn't writable,
437198090Srdivacky    //      we need to use some form of indirection.  For example, on Darwin,
438198090Srdivacky    //      we can output a statically-relocatable reference to a dyld stub. The
439198090Srdivacky    //      offset to the stub is constant, but the contents are in a section
440198090Srdivacky    //      that is updated by the dynamic linker.  This is easy enough, but we
441198090Srdivacky    //      need to tell the personality function of the unwinder to indirect
442198090Srdivacky    //      through the dyld stub.
443198090Srdivacky    //
444198090Srdivacky    // FIXME: When (3) is actually implemented, we'll have to emit the stubs
445198090Srdivacky    // somewhere.  This predicate should be moved to a shared location that is
446198090Srdivacky    // in target-independent code.
447198090Srdivacky    //
448203954Srdivacky    TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding();
449206274Srdivacky    TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding);
450198090Srdivacky  }
451193323Sed
452193323Sed  // Begin the exception table.
453218893Sdim  // Sometimes we want not to emit the data into separate section (e.g. ARM
454218893Sdim  // EHABI). In this case LSDASection will be NULL.
455218893Sdim  if (LSDASection)
456218893Sdim    Asm->OutStreamer.SwitchSection(LSDASection);
457207618Srdivacky  Asm->EmitAlignment(2);
458198090Srdivacky
459204642Srdivacky  // Emit the LSDA.
460218893Sdim  MCSymbol *GCCETSym =
461204961Srdivacky    Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+
462206274Srdivacky                                      Twine(Asm->getFunctionNumber()));
463204961Srdivacky  Asm->OutStreamer.EmitLabel(GCCETSym);
464206274Srdivacky  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("exception",
465206274Srdivacky                                                Asm->getFunctionNumber()));
466193323Sed
467204961Srdivacky  if (IsSJLJ)
468206274Srdivacky    Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("_LSDA_",
469206274Srdivacky                                                  Asm->getFunctionNumber()));
470204642Srdivacky
471204642Srdivacky  // Emit the LSDA header.
472206274Srdivacky  Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
473206274Srdivacky  Asm->EmitEncodingByte(TTypeEncoding, "@TType");
474204642Srdivacky
475198090Srdivacky  // The type infos need to be aligned. GCC does this by inserting padding just
476198090Srdivacky  // before the type infos. However, this changes the size of the exception
477198090Srdivacky  // table, so you need to take this into account when you output the exception
478198090Srdivacky  // table size. However, the size is output using a variable length encoding.
479198090Srdivacky  // So by increasing the size by inserting padding, you may increase the number
480198090Srdivacky  // of bytes used for writing the size. If it increases, say by one byte, then
481198090Srdivacky  // you now need to output one less byte of padding to get the type infos
482204642Srdivacky  // aligned. However this decreases the size of the exception table. This
483198090Srdivacky  // changes the value you have to output for the exception table size. Due to
484198090Srdivacky  // the variable length encoding, the number of bytes used for writing the
485198090Srdivacky  // length may decrease. If so, you then have to increase the amount of
486198090Srdivacky  // padding. And so on. If you look carefully at the GCC code you will see that
487198090Srdivacky  // it indeed does this in a loop, going on and on until the values stabilize.
488198090Srdivacky  // We chose another solution: don't output padding inside the table like GCC
489198090Srdivacky  // does, instead output it before the table.
490198090Srdivacky  unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
491204642Srdivacky  unsigned CallSiteTableLengthSize =
492204642Srdivacky    MCAsmInfo::getULEB128Size(CallSiteTableLength);
493204642Srdivacky  unsigned TTypeBaseOffset =
494204642Srdivacky    sizeof(int8_t) +                            // Call site format
495204642Srdivacky    CallSiteTableLengthSize +                   // Call site table length size
496204642Srdivacky    CallSiteTableLength +                       // Call site table length
497204642Srdivacky    SizeActions +                               // Actions size
498204642Srdivacky    SizeTypes;
499204642Srdivacky  unsigned TTypeBaseOffsetSize = MCAsmInfo::getULEB128Size(TTypeBaseOffset);
500204642Srdivacky  unsigned TotalSize =
501204642Srdivacky    sizeof(int8_t) +                            // LPStart format
502204642Srdivacky    sizeof(int8_t) +                            // TType format
503204642Srdivacky    (HaveTTData ? TTypeBaseOffsetSize : 0) +    // TType base offset size
504204642Srdivacky    TTypeBaseOffset;                            // TType base offset
505198090Srdivacky  unsigned SizeAlign = (4 - TotalSize) & 3;
506198090Srdivacky
507204642Srdivacky  if (HaveTTData) {
508204642Srdivacky    // Account for any extra padding that will be added to the call site table
509204642Srdivacky    // length.
510206274Srdivacky    Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign);
511204642Srdivacky    SizeAlign = 0;
512198090Srdivacky  }
513193323Sed
514224145Sdim  bool VerboseAsm = Asm->OutStreamer.isVerboseAsm();
515224145Sdim
516198090Srdivacky  // SjLj Exception handling
517198090Srdivacky  if (IsSJLJ) {
518206274Srdivacky    Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
519198090Srdivacky
520204642Srdivacky    // Add extra padding if it wasn't added to the TType base offset.
521206274Srdivacky    Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
522204642Srdivacky
523198090Srdivacky    // Emit the landing pad site information.
524198090Srdivacky    unsigned idx = 0;
525198090Srdivacky    for (SmallVectorImpl<CallSiteEntry>::const_iterator
526198090Srdivacky         I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) {
527198090Srdivacky      const CallSiteEntry &S = *I;
528198090Srdivacky
529226890Sdim      // Offset of the landing pad, counted in 16-byte bundles relative to the
530226890Sdim      // @LPStart address.
531224145Sdim      if (VerboseAsm) {
532235633Sdim        Asm->OutStreamer.AddComment(">> Call Site " + Twine(idx) + " <<");
533235633Sdim        Asm->OutStreamer.AddComment("  On exception at call site "+Twine(idx));
534226890Sdim      }
535226890Sdim      Asm->EmitULEB128(idx);
536224145Sdim
537226890Sdim      // Offset of the first associated action record, relative to the start of
538226890Sdim      // the action table. This value is biased by 1 (1 indicates the start of
539226890Sdim      // the action table), and 0 indicates that there are no actions.
540226890Sdim      if (VerboseAsm) {
541224145Sdim        if (S.Action == 0)
542224145Sdim          Asm->OutStreamer.AddComment("  Action: cleanup");
543224145Sdim        else
544235633Sdim          Asm->OutStreamer.AddComment("  Action: " +
545235633Sdim                                      Twine((S.Action - 1) / 2 + 1));
546224145Sdim      }
547224145Sdim      Asm->EmitULEB128(S.Action);
548193323Sed    }
549198090Srdivacky  } else {
550198090Srdivacky    // DWARF Exception handling
551218893Sdim    assert(Asm->MAI->isExceptionHandlingDwarf());
552193323Sed
553198090Srdivacky    // The call-site table is a list of all call sites that may throw an
554198090Srdivacky    // exception (including C++ 'throw' statements) in the procedure
555198090Srdivacky    // fragment. It immediately follows the LSDA header. Each entry indicates,
556198090Srdivacky    // for a given call, the first corresponding action record and corresponding
557198090Srdivacky    // landing pad.
558198090Srdivacky    //
559198090Srdivacky    // The table begins with the number of bytes, stored as an LEB128
560198090Srdivacky    // compressed, unsigned integer. The records immediately follow the record
561198090Srdivacky    // count. They are sorted in increasing call-site address. Each record
562198090Srdivacky    // indicates:
563198090Srdivacky    //
564198090Srdivacky    //   * The position of the call-site.
565198090Srdivacky    //   * The position of the landing pad.
566198090Srdivacky    //   * The first action record for that call site.
567198090Srdivacky    //
568198090Srdivacky    // A missing entry in the call-site table indicates that a call is not
569198090Srdivacky    // supposed to throw.
570193323Sed
571198090Srdivacky    // Emit the landing pad call site table.
572206274Srdivacky    Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
573193323Sed
574204642Srdivacky    // Add extra padding if it wasn't added to the TType base offset.
575206274Srdivacky    Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
576204642Srdivacky
577224145Sdim    unsigned Entry = 0;
578198090Srdivacky    for (SmallVectorImpl<CallSiteEntry>::const_iterator
579198090Srdivacky         I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
580198090Srdivacky      const CallSiteEntry &S = *I;
581218893Sdim
582206274Srdivacky      MCSymbol *EHFuncBeginSym =
583206274Srdivacky        Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber());
584218893Sdim
585205218Srdivacky      MCSymbol *BeginLabel = S.BeginLabel;
586205218Srdivacky      if (BeginLabel == 0)
587205218Srdivacky        BeginLabel = EHFuncBeginSym;
588205218Srdivacky      MCSymbol *EndLabel = S.EndLabel;
589205218Srdivacky      if (EndLabel == 0)
590206274Srdivacky        EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber());
591218893Sdim
592226890Sdim
593226890Sdim      // Offset of the call site relative to the previous call site, counted in
594226890Sdim      // number of 16-byte bundles. The first call site is counted relative to
595226890Sdim      // the start of the procedure fragment.
596226890Sdim      if (VerboseAsm)
597235633Sdim        Asm->OutStreamer.AddComment(">> Call Site " + Twine(++Entry) + " <<");
598226890Sdim      Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
599226890Sdim      if (VerboseAsm)
600224145Sdim        Asm->OutStreamer.AddComment(Twine("  Call between ") +
601224145Sdim                                    BeginLabel->getName() + " and " +
602224145Sdim                                    EndLabel->getName());
603206274Srdivacky      Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
604193323Sed
605198090Srdivacky      // Offset of the landing pad, counted in 16-byte bundles relative to the
606198090Srdivacky      // @LPStart address.
607226890Sdim      if (!S.PadLabel) {
608226890Sdim        if (VerboseAsm)
609226890Sdim          Asm->OutStreamer.AddComment("    has no landing pad");
610252723Sdim        Asm->OutStreamer.EmitIntValue(0, 4/*size*/);
611226890Sdim      } else {
612226890Sdim        if (VerboseAsm)
613226890Sdim          Asm->OutStreamer.AddComment(Twine("    jumps to ") +
614226890Sdim                                      S.PadLabel->getName());
615206274Srdivacky        Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4);
616226890Sdim      }
617198090Srdivacky
618198090Srdivacky      // Offset of the first associated action record, relative to the start of
619198090Srdivacky      // the action table. This value is biased by 1 (1 indicates the start of
620198090Srdivacky      // the action table), and 0 indicates that there are no actions.
621226890Sdim      if (VerboseAsm) {
622226890Sdim        if (S.Action == 0)
623226890Sdim          Asm->OutStreamer.AddComment("  On action: cleanup");
624226890Sdim        else
625235633Sdim          Asm->OutStreamer.AddComment("  On action: " +
626235633Sdim                                      Twine((S.Action - 1) / 2 + 1));
627226890Sdim      }
628224145Sdim      Asm->EmitULEB128(S.Action);
629198090Srdivacky    }
630193323Sed  }
631193323Sed
632198090Srdivacky  // Emit the Action Table.
633224145Sdim  int Entry = 0;
634198090Srdivacky  for (SmallVectorImpl<ActionEntry>::const_iterator
635198090Srdivacky         I = Actions.begin(), E = Actions.end(); I != E; ++I) {
636198090Srdivacky    const ActionEntry &Action = *I;
637193323Sed
638224145Sdim    if (VerboseAsm) {
639224145Sdim      // Emit comments that decode the action table.
640235633Sdim      Asm->OutStreamer.AddComment(">> Action Record " + Twine(++Entry) + " <<");
641226890Sdim    }
642226890Sdim
643226890Sdim    // Type Filter
644226890Sdim    //
645226890Sdim    //   Used by the runtime to match the type of the thrown exception to the
646226890Sdim    //   type of the catch clauses or the types in the exception specification.
647226890Sdim    if (VerboseAsm) {
648226890Sdim      if (Action.ValueForTypeID > 0)
649235633Sdim        Asm->OutStreamer.AddComment("  Catch TypeInfo " +
650235633Sdim                                    Twine(Action.ValueForTypeID));
651226890Sdim      else if (Action.ValueForTypeID < 0)
652235633Sdim        Asm->OutStreamer.AddComment("  Filter TypeInfo " +
653235633Sdim                                    Twine(Action.ValueForTypeID));
654226890Sdim      else
655226890Sdim        Asm->OutStreamer.AddComment("  Cleanup");
656226890Sdim    }
657226890Sdim    Asm->EmitSLEB128(Action.ValueForTypeID);
658224145Sdim
659226890Sdim    // Action Record
660226890Sdim    //
661226890Sdim    //   Self-relative signed displacement in bytes of the next action record,
662226890Sdim    //   or 0 if there is no next action record.
663226890Sdim    if (VerboseAsm) {
664224145Sdim      if (Action.NextAction == 0) {
665224145Sdim        Asm->OutStreamer.AddComment("  No further actions");
666224145Sdim      } else {
667224145Sdim        unsigned NextAction = Entry + (Action.NextAction + 1) / 2;
668235633Sdim        Asm->OutStreamer.AddComment("  Continue to action "+Twine(NextAction));
669224145Sdim      }
670224145Sdim    }
671224145Sdim    Asm->EmitSLEB128(Action.NextAction);
672193323Sed  }
673193323Sed
674252723Sdim  EmitTypeInfos(TTypeEncoding);
675252723Sdim
676252723Sdim  Asm->EmitAlignment(2);
677252723Sdim}
678252723Sdim
679252723Sdimvoid DwarfException::EmitTypeInfos(unsigned TTypeEncoding) {
680252723Sdim  const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
681252723Sdim  const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
682252723Sdim
683252723Sdim  bool VerboseAsm = Asm->OutStreamer.isVerboseAsm();
684252723Sdim
685252723Sdim  int Entry = 0;
686198396Srdivacky  // Emit the Catch TypeInfos.
687224145Sdim  if (VerboseAsm && !TypeInfos.empty()) {
688224145Sdim    Asm->OutStreamer.AddComment(">> Catch TypeInfos <<");
689204961Srdivacky    Asm->OutStreamer.AddBlankLine();
690224145Sdim    Entry = TypeInfos.size();
691204961Srdivacky  }
692224145Sdim
693207618Srdivacky  for (std::vector<const GlobalVariable *>::const_reverse_iterator
694198090Srdivacky         I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) {
695199989Srdivacky    const GlobalVariable *GV = *I;
696224145Sdim    if (VerboseAsm)
697235633Sdim      Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--));
698252723Sdim    Asm->EmitTTypeReference(GV, TTypeEncoding);
699193323Sed  }
700193323Sed
701198396Srdivacky  // Emit the Exception Specifications.
702224145Sdim  if (VerboseAsm && !FilterIds.empty()) {
703224145Sdim    Asm->OutStreamer.AddComment(">> Filter TypeInfos <<");
704204961Srdivacky    Asm->OutStreamer.AddBlankLine();
705224145Sdim    Entry = 0;
706204961Srdivacky  }
707198090Srdivacky  for (std::vector<unsigned>::const_iterator
708198090Srdivacky         I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
709198090Srdivacky    unsigned TypeID = *I;
710224145Sdim    if (VerboseAsm) {
711224145Sdim      --Entry;
712224145Sdim      if (TypeID != 0)
713235633Sdim        Asm->OutStreamer.AddComment("FilterInfo " + Twine(Entry));
714224145Sdim    }
715224145Sdim
716224145Sdim    Asm->EmitULEB128(TypeID);
717193323Sed  }
718193323Sed}
719193323Sed
720193323Sed/// EndModule - Emit all exception information that should come after the
721193323Sed/// content.
722193323Sedvoid DwarfException::EndModule() {
723235633Sdim  llvm_unreachable("Should be implemented");
724193323Sed}
725193323Sed
726198090Srdivacky/// BeginFunction - Gather pre-function exception information. Assumes it's
727198090Srdivacky/// being emitted immediately after the function entry point.
728203954Srdivackyvoid DwarfException::BeginFunction(const MachineFunction *MF) {
729235633Sdim  llvm_unreachable("Should be implemented");
730193323Sed}
731193323Sed
732193323Sed/// EndFunction - Gather and emit post-function exception information.
733193323Sed///
734193323Sedvoid DwarfException::EndFunction() {
735235633Sdim  llvm_unreachable("Should be implemented");
736193323Sed}
737