1 //===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains support for writing dwarf exception info into asm files.
12 //===----------------------------------------------------------------------===//
14 #include "DwarfException.h"
15 #include "llvm/Module.h"
16 #include "llvm/CodeGen/MachineModuleInfo.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineLocation.h"
19 #include "llvm/Support/Dwarf.h"
20 #include "llvm/Support/Timer.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/Target/TargetAsmInfo.h"
23 #include "llvm/Target/TargetData.h"
24 #include "llvm/Target/TargetFrameInfo.h"
25 #include "llvm/Target/TargetLoweringObjectFile.h"
26 #include "llvm/Target/TargetOptions.h"
27 #include "llvm/Target/TargetRegisterInfo.h"
28 #include "llvm/ADT/StringExtras.h"
31 static TimerGroup
&getDwarfTimerGroup() {
32 static TimerGroup
DwarfTimerGroup("Dwarf Exception");
33 return DwarfTimerGroup
;
36 DwarfException::DwarfException(raw_ostream
&OS
, AsmPrinter
*A
,
37 const TargetAsmInfo
*T
)
38 : Dwarf(OS
, A
, T
, "eh"), shouldEmitTable(false), shouldEmitMoves(false),
39 shouldEmitTableModule(false), shouldEmitMovesModule(false),
41 if (TimePassesIsEnabled
)
42 ExceptionTimer
= new Timer("Dwarf Exception Writer",
43 getDwarfTimerGroup());
46 DwarfException::~DwarfException() {
47 delete ExceptionTimer
;
50 void DwarfException::EmitCommonEHFrame(const Function
*Personality
,
52 // Size and sign of stack growth.
54 Asm
->TM
.getFrameInfo()->getStackGrowthDirection() ==
55 TargetFrameInfo::StackGrowsUp
?
56 TD
->getPointerSize() : -TD
->getPointerSize();
58 // Begin eh frame section.
59 Asm
->SwitchToSection(Asm
->getObjFileLowering().getEHFrameSection());
61 if (TAI
->is_EHSymbolPrivate())
62 O
<< TAI
->getPrivateGlobalPrefix();
64 O
<< "EH_frame" << Index
<< ":\n";
65 EmitLabel("section_eh_frame", Index
);
67 // Define base labels.
68 EmitLabel("eh_frame_common", Index
);
70 // Define the eh frame length.
71 EmitDifference("eh_frame_common_end", Index
,
72 "eh_frame_common_begin", Index
, true);
73 Asm
->EOL("Length of Common Information Entry");
76 EmitLabel("eh_frame_common_begin", Index
);
77 Asm
->EmitInt32((int)0);
78 Asm
->EOL("CIE Identifier Tag");
79 Asm
->EmitInt8(dwarf::DW_CIE_VERSION
);
80 Asm
->EOL("CIE Version");
82 // The personality presence indicates that language specific information will
83 // show up in the eh frame.
84 Asm
->EmitString(Personality
? "zPLR" : "zR");
85 Asm
->EOL("CIE Augmentation");
88 Asm
->EmitULEB128Bytes(1);
89 Asm
->EOL("CIE Code Alignment Factor");
90 Asm
->EmitSLEB128Bytes(stackGrowth
);
91 Asm
->EOL("CIE Data Alignment Factor");
92 Asm
->EmitInt8(RI
->getDwarfRegNum(RI
->getRARegister(), true));
93 Asm
->EOL("CIE Return Address Column");
95 // If there is a personality, we need to indicate the functions location.
97 Asm
->EmitULEB128Bytes(7);
98 Asm
->EOL("Augmentation Size");
100 if (TAI
->getNeedsIndirectEncoding()) {
101 Asm
->EmitInt8(dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_sdata4
|
102 dwarf::DW_EH_PE_indirect
);
103 Asm
->EOL("Personality (pcrel sdata4 indirect)");
105 Asm
->EmitInt8(dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_sdata4
);
106 Asm
->EOL("Personality (pcrel sdata4)");
109 PrintRelDirective(true);
110 O
<< TAI
->getPersonalityPrefix();
111 Asm
->EmitExternalGlobal((const GlobalVariable
*)(Personality
));
112 O
<< TAI
->getPersonalitySuffix();
113 if (strcmp(TAI
->getPersonalitySuffix(), "+4@GOTPCREL"))
114 O
<< "-" << TAI
->getPCSymbol();
115 Asm
->EOL("Personality");
117 Asm
->EmitInt8(dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_sdata4
);
118 Asm
->EOL("LSDA Encoding (pcrel sdata4)");
120 Asm
->EmitInt8(dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_sdata4
);
121 Asm
->EOL("FDE Encoding (pcrel sdata4)");
123 Asm
->EmitULEB128Bytes(1);
124 Asm
->EOL("Augmentation Size");
126 Asm
->EmitInt8(dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_sdata4
);
127 Asm
->EOL("FDE Encoding (pcrel sdata4)");
130 // Indicate locations of general callee saved registers in frame.
131 std::vector
<MachineMove
> Moves
;
132 RI
->getInitialFrameState(Moves
);
133 EmitFrameMoves(NULL
, 0, Moves
, true);
135 // On Darwin the linker honors the alignment of eh_frame, which means it must
136 // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get
137 // holes which confuse readers of eh_frame.
138 Asm
->EmitAlignment(TD
->getPointerSize() == sizeof(int32_t) ? 2 : 3,
140 EmitLabel("eh_frame_common_end", Index
);
145 /// EmitEHFrame - Emit function exception frame information.
147 void DwarfException::EmitEHFrame(const FunctionEHFrameInfo
&EHFrameInfo
) {
148 assert(!EHFrameInfo
.function
->hasAvailableExternallyLinkage() &&
149 "Should not emit 'available externally' functions at all");
151 const Function
*TheFunc
= EHFrameInfo
.function
;
153 Asm
->SwitchToSection(Asm
->getObjFileLowering().getEHFrameSection());
155 // Externally visible entry into the functions eh frame info. If the
156 // corresponding function is static, this should not be externally visible.
157 if (!TheFunc
->hasLocalLinkage())
158 if (const char *GlobalEHDirective
= TAI
->getGlobalEHDirective())
159 O
<< GlobalEHDirective
<< EHFrameInfo
.FnName
<< "\n";
161 // If corresponding function is weak definition, this should be too.
162 if (TheFunc
->isWeakForLinker() && TAI
->getWeakDefDirective())
163 O
<< TAI
->getWeakDefDirective() << EHFrameInfo
.FnName
<< "\n";
165 // If there are no calls then you can't unwind. This may mean we can omit the
166 // EH Frame, but some environments do not handle weak absolute symbols. If
167 // UnwindTablesMandatory is set we cannot do this optimization; the unwind
168 // info is to be available for non-EH uses.
169 if (!EHFrameInfo
.hasCalls
&& !UnwindTablesMandatory
&&
170 (!TheFunc
->isWeakForLinker() ||
171 !TAI
->getWeakDefDirective() ||
172 TAI
->getSupportsWeakOmittedEHFrame())) {
173 O
<< EHFrameInfo
.FnName
<< " = 0\n";
174 // This name has no connection to the function, so it might get
175 // dead-stripped when the function is not, erroneously. Prohibit
176 // dead-stripping unconditionally.
177 if (const char *UsedDirective
= TAI
->getUsedDirective())
178 O
<< UsedDirective
<< EHFrameInfo
.FnName
<< "\n\n";
180 O
<< EHFrameInfo
.FnName
<< ":\n";
183 EmitDifference("eh_frame_end", EHFrameInfo
.Number
,
184 "eh_frame_begin", EHFrameInfo
.Number
, true);
185 Asm
->EOL("Length of Frame Information Entry");
187 EmitLabel("eh_frame_begin", EHFrameInfo
.Number
);
189 EmitSectionOffset("eh_frame_begin", "eh_frame_common",
190 EHFrameInfo
.Number
, EHFrameInfo
.PersonalityIndex
,
193 Asm
->EOL("FDE CIE offset");
195 EmitReference("eh_func_begin", EHFrameInfo
.Number
, true, true);
196 Asm
->EOL("FDE initial location");
197 EmitDifference("eh_func_end", EHFrameInfo
.Number
,
198 "eh_func_begin", EHFrameInfo
.Number
, true);
199 Asm
->EOL("FDE address range");
201 // If there is a personality and landing pads then point to the language
202 // specific data area in the exception table.
203 if (EHFrameInfo
.PersonalityIndex
) {
204 Asm
->EmitULEB128Bytes(4);
205 Asm
->EOL("Augmentation size");
207 if (EHFrameInfo
.hasLandingPads
)
208 EmitReference("exception", EHFrameInfo
.Number
, true, true);
210 Asm
->EmitInt32((int)0);
211 Asm
->EOL("Language Specific Data Area");
213 Asm
->EmitULEB128Bytes(0);
214 Asm
->EOL("Augmentation size");
217 // Indicate locations of function specific callee saved registers in frame.
218 EmitFrameMoves("eh_func_begin", EHFrameInfo
.Number
, EHFrameInfo
.Moves
,
221 // On Darwin the linker honors the alignment of eh_frame, which means it
222 // must be 8-byte on 64-bit targets to match what gcc does. Otherwise you
223 // get holes which confuse readers of eh_frame.
224 Asm
->EmitAlignment(TD
->getPointerSize() == sizeof(int32_t) ? 2 : 3,
226 EmitLabel("eh_frame_end", EHFrameInfo
.Number
);
228 // If the function is marked used, this table should be also. We cannot
229 // make the mark unconditional in this case, since retaining the table also
230 // retains the function in this case, and there is code around that depends
231 // on unused functions (calling undefined externals) being dead-stripped to
232 // link correctly. Yes, there really is.
233 if (MMI
->isUsedFunction(EHFrameInfo
.function
))
234 if (const char *UsedDirective
= TAI
->getUsedDirective())
235 O
<< UsedDirective
<< EHFrameInfo
.FnName
<< "\n\n";
239 /// SharedTypeIds - How many leading type ids two landing pads have in common.
240 unsigned DwarfException::SharedTypeIds(const LandingPadInfo
*L
,
241 const LandingPadInfo
*R
) {
242 const std::vector
<int> &LIds
= L
->TypeIds
, &RIds
= R
->TypeIds
;
243 unsigned LSize
= LIds
.size(), RSize
= RIds
.size();
244 unsigned MinSize
= LSize
< RSize
? LSize
: RSize
;
247 for (; Count
!= MinSize
; ++Count
)
248 if (LIds
[Count
] != RIds
[Count
])
254 /// PadLT - Order landing pads lexicographically by type id.
255 bool DwarfException::PadLT(const LandingPadInfo
*L
, const LandingPadInfo
*R
) {
256 const std::vector
<int> &LIds
= L
->TypeIds
, &RIds
= R
->TypeIds
;
257 unsigned LSize
= LIds
.size(), RSize
= RIds
.size();
258 unsigned MinSize
= LSize
< RSize
? LSize
: RSize
;
260 for (unsigned i
= 0; i
!= MinSize
; ++i
)
261 if (LIds
[i
] != RIds
[i
])
262 return LIds
[i
] < RIds
[i
];
264 return LSize
< RSize
;
267 /// ComputeActionsTable - Compute the actions table and gather the first action
268 /// index for each landing pad site.
269 unsigned DwarfException::
270 ComputeActionsTable(const SmallVectorImpl
<const LandingPadInfo
*> &LandingPads
,
271 SmallVectorImpl
<ActionEntry
> &Actions
,
272 SmallVectorImpl
<unsigned> &FirstActions
) {
273 // Negative type IDs index into FilterIds. Positive type IDs index into
274 // TypeInfos. The value written for a positive type ID is just the type ID
275 // itself. For a negative type ID, however, the value written is the
276 // (negative) byte offset of the corresponding FilterIds entry. The byte
277 // offset is usually equal to the type ID (because the FilterIds entries are
278 // written using a variable width encoding, which outputs one byte per entry
279 // as long as the value written is not too large) but can differ. This kind
280 // of complication does not occur for positive type IDs because type infos are
281 // output using a fixed width encoding. FilterOffsets[i] holds the byte
282 // offset corresponding to FilterIds[i].
284 const std::vector
<unsigned> &FilterIds
= MMI
->getFilterIds();
285 SmallVector
<int, 16> FilterOffsets
;
286 FilterOffsets
.reserve(FilterIds
.size());
289 for (std::vector
<unsigned>::const_iterator
290 I
= FilterIds
.begin(), E
= FilterIds
.end(); I
!= E
; ++I
) {
291 FilterOffsets
.push_back(Offset
);
292 Offset
-= TargetAsmInfo::getULEB128Size(*I
);
295 FirstActions
.reserve(LandingPads
.size());
298 unsigned SizeActions
= 0;
299 const LandingPadInfo
*PrevLPI
= 0;
301 for (SmallVectorImpl
<const LandingPadInfo
*>::const_iterator
302 I
= LandingPads
.begin(), E
= LandingPads
.end(); I
!= E
; ++I
) {
303 const LandingPadInfo
*LPI
= *I
;
304 const std::vector
<int> &TypeIds
= LPI
->TypeIds
;
305 const unsigned NumShared
= PrevLPI
? SharedTypeIds(LPI
, PrevLPI
) : 0;
306 unsigned SizeSiteActions
= 0;
308 if (NumShared
< TypeIds
.size()) {
309 unsigned SizeAction
= 0;
310 ActionEntry
*PrevAction
= 0;
313 const unsigned SizePrevIds
= PrevLPI
->TypeIds
.size();
314 assert(Actions
.size());
315 PrevAction
= &Actions
.back();
316 SizeAction
= TargetAsmInfo::getSLEB128Size(PrevAction
->NextAction
) +
317 TargetAsmInfo::getSLEB128Size(PrevAction
->ValueForTypeID
);
319 for (unsigned j
= NumShared
; j
!= SizePrevIds
; ++j
) {
321 TargetAsmInfo::getSLEB128Size(PrevAction
->ValueForTypeID
);
322 SizeAction
+= -PrevAction
->NextAction
;
323 PrevAction
= PrevAction
->Previous
;
327 // Compute the actions.
328 for (unsigned J
= NumShared
, M
= TypeIds
.size(); J
!= M
; ++J
) {
329 int TypeID
= TypeIds
[J
];
330 assert(-1 - TypeID
< (int)FilterOffsets
.size() && "Unknown filter id!");
331 int ValueForTypeID
= TypeID
< 0 ? FilterOffsets
[-1 - TypeID
] : TypeID
;
332 unsigned SizeTypeID
= TargetAsmInfo::getSLEB128Size(ValueForTypeID
);
334 int NextAction
= SizeAction
? -(SizeAction
+ SizeTypeID
) : 0;
335 SizeAction
= SizeTypeID
+ TargetAsmInfo::getSLEB128Size(NextAction
);
336 SizeSiteActions
+= SizeAction
;
338 ActionEntry Action
= {ValueForTypeID
, NextAction
, PrevAction
};
339 Actions
.push_back(Action
);
340 PrevAction
= &Actions
.back();
343 // Record the first action of the landing pad site.
344 FirstAction
= SizeActions
+ SizeSiteActions
- SizeAction
+ 1;
345 } // else identical - re-use previous FirstAction
347 FirstActions
.push_back(FirstAction
);
349 // Compute this sites contribution to size.
350 SizeActions
+= SizeSiteActions
;
358 /// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke
359 /// has a try-range containing the call, a non-zero landing pad and an
360 /// appropriate action. The entry for an ordinary call has a try-range
361 /// containing the call and zero for the landing pad and the action. Calls
362 /// marked 'nounwind' have no entry and must not be contained in the try-range
363 /// of any entry - they form gaps in the table. Entries must be ordered by
364 /// try-range address.
365 void DwarfException::
366 ComputeCallSiteTable(SmallVectorImpl
<CallSiteEntry
> &CallSites
,
367 std::map
<unsigned,CallSiteEntry
*> &CallSiteIndexMap
,
368 const RangeMapType
&PadMap
,
369 const SmallVectorImpl
<const LandingPadInfo
*> &LandingPads
,
370 const SmallVectorImpl
<unsigned> &FirstActions
) {
371 // The end label of the previous invoke or nounwind try-range.
372 unsigned LastLabel
= 0;
374 // Whether there is a potentially throwing instruction (currently this means
375 // an ordinary call) between the end of the previous try-range and now.
376 bool SawPotentiallyThrowing
= false;
378 // Whether the last CallSite entry was for an invoke.
379 bool PreviousIsInvoke
= false;
381 // Visit all instructions in order of address.
382 for (MachineFunction::const_iterator I
= MF
->begin(), E
= MF
->end();
384 for (MachineBasicBlock::const_iterator MI
= I
->begin(), E
= I
->end();
386 if (!MI
->isLabel()) {
387 SawPotentiallyThrowing
|= MI
->getDesc().isCall();
391 unsigned BeginLabel
= MI
->getOperand(0).getImm();
392 assert(BeginLabel
&& "Invalid label!");
394 // End of the previous try-range?
395 if (BeginLabel
== LastLabel
)
396 SawPotentiallyThrowing
= false;
398 // Beginning of a new try-range?
399 RangeMapType::iterator L
= PadMap
.find(BeginLabel
);
400 if (L
== PadMap
.end())
401 // Nope, it was just some random label.
404 PadRange P
= L
->second
;
405 const LandingPadInfo
*LandingPad
= LandingPads
[P
.PadIndex
];
406 assert(BeginLabel
== LandingPad
->BeginLabels
[P
.RangeIndex
] &&
407 "Inconsistent landing pad map!");
409 // For Dwarf exception handling (SjLj handling doesn't use this)
410 // If some instruction between the previous try-range and this one may
411 // throw, create a call-site entry with no landing pad for the region
412 // between the try-ranges.
413 if (SawPotentiallyThrowing
&&
414 TAI
->getExceptionHandlingType() == ExceptionHandling::Dwarf
) {
415 CallSiteEntry Site
= {LastLabel
, BeginLabel
, 0, 0};
416 CallSites
.push_back(Site
);
417 PreviousIsInvoke
= false;
420 LastLabel
= LandingPad
->EndLabels
[P
.RangeIndex
];
421 assert(BeginLabel
&& LastLabel
&& "Invalid landing pad!");
423 if (LandingPad
->LandingPadLabel
) {
424 // This try-range is for an invoke.
425 CallSiteEntry Site
= {BeginLabel
, LastLabel
,
426 LandingPad
->LandingPadLabel
,
427 FirstActions
[P
.PadIndex
]};
429 // Try to merge with the previous call-site.
430 if (PreviousIsInvoke
) {
431 CallSiteEntry
&Prev
= CallSites
.back();
432 if (Site
.PadLabel
== Prev
.PadLabel
&& Site
.Action
== Prev
.Action
) {
433 // Extend the range of the previous entry.
434 Prev
.EndLabel
= Site
.EndLabel
;
439 // Otherwise, create a new call-site.
440 CallSites
.push_back(Site
);
441 // For SjLj handling, map the call site entry to its index
442 if (TAI
->getExceptionHandlingType() == ExceptionHandling::SjLj
) {
444 MF
->getLandingPadCallSiteIndex(LandingPad
->LandingPadBlock
);
445 CallSiteIndexMap
[Index
] = &CallSites
.back();
447 PreviousIsInvoke
= true;
450 PreviousIsInvoke
= false;
455 // If some instruction between the previous try-range and the end of the
456 // function may throw, create a call-site entry with no landing pad for the
457 // region following the try-range.
458 if (SawPotentiallyThrowing
&&
459 TAI
->getExceptionHandlingType() == ExceptionHandling::Dwarf
) {
460 CallSiteEntry Site
= {LastLabel
, 0, 0, 0};
461 CallSites
.push_back(Site
);
465 /// EmitExceptionTable - Emit landing pads and actions.
467 /// The general organization of the table is complex, but the basic concepts are
468 /// easy. First there is a header which describes the location and organization
469 /// of the three components that follow.
471 /// 1. The landing pad site information describes the range of code covered by
472 /// the try. In our case it's an accumulation of the ranges covered by the
473 /// invokes in the try. There is also a reference to the landing pad that
474 /// handles the exception once processed. Finally an index into the actions
476 /// 2. The action table, in our case, is composed of pairs of type ids and next
477 /// action offset. Starting with the action index from the landing pad
478 /// site, each type Id is checked for a match to the current exception. If
479 /// it matches then the exception and type id are passed on to the landing
480 /// pad. Otherwise the next action is looked up. This chain is terminated
481 /// with a next action of zero. If no type id is found the the frame is
482 /// unwound and handling continues.
483 /// 3. Type id table contains references to all the C++ typeinfo for all
484 /// catches in the function. This tables is reversed indexed base 1.
485 void DwarfException::EmitExceptionTable() {
486 const std::vector
<GlobalVariable
*> &TypeInfos
= MMI
->getTypeInfos();
487 const std::vector
<unsigned> &FilterIds
= MMI
->getFilterIds();
488 const std::vector
<LandingPadInfo
> &PadInfos
= MMI
->getLandingPads();
489 if (PadInfos
.empty()) return;
491 // Sort the landing pads in order of their type ids. This is used to fold
492 // duplicate actions.
493 SmallVector
<const LandingPadInfo
*, 64> LandingPads
;
494 LandingPads
.reserve(PadInfos
.size());
496 for (unsigned i
= 0, N
= PadInfos
.size(); i
!= N
; ++i
)
497 LandingPads
.push_back(&PadInfos
[i
]);
499 std::sort(LandingPads
.begin(), LandingPads
.end(), PadLT
);
501 // Compute the actions table and gather the first action index for each
503 SmallVector
<ActionEntry
, 32> Actions
;
504 SmallVector
<unsigned, 64> FirstActions
;
505 unsigned SizeActions
= ComputeActionsTable(LandingPads
, Actions
, FirstActions
);
507 // Invokes and nounwind calls have entries in PadMap (due to being bracketed
508 // by try-range labels when lowered). Ordinary calls do not, so appropriate
509 // try-ranges for them need be deduced when using Dwarf exception handling.
511 for (unsigned i
= 0, N
= LandingPads
.size(); i
!= N
; ++i
) {
512 const LandingPadInfo
*LandingPad
= LandingPads
[i
];
513 for (unsigned j
= 0, E
= LandingPad
->BeginLabels
.size(); j
!= E
; ++j
) {
514 unsigned BeginLabel
= LandingPad
->BeginLabels
[j
];
515 assert(!PadMap
.count(BeginLabel
) && "Duplicate landing pad labels!");
516 PadRange P
= { i
, j
};
517 PadMap
[BeginLabel
] = P
;
521 // Compute the call-site table.
522 SmallVector
<CallSiteEntry
, 64> CallSites
;
523 std::map
<unsigned,CallSiteEntry
*> CallSiteIndexMap
;
524 ComputeCallSiteTable(CallSites
, CallSiteIndexMap
, PadMap
,
525 LandingPads
, FirstActions
);
530 const unsigned SiteStartSize
= sizeof(int32_t); // DW_EH_PE_udata4
531 const unsigned SiteLengthSize
= sizeof(int32_t); // DW_EH_PE_udata4
532 const unsigned LandingPadSize
= sizeof(int32_t); // DW_EH_PE_udata4
535 bool HaveTTData
= (TAI
->getExceptionHandlingType() == ExceptionHandling::SjLj
)
536 ? (!TypeInfos
.empty() || !FilterIds
.empty()) : true;
539 if (TAI
->getExceptionHandlingType() == ExceptionHandling::SjLj
) {
540 SizeSites
= (MF
->getMaxCallSiteIndex() - CallSites
.size()) *
541 TargetAsmInfo::getULEB128Size(0) * 2;
543 SizeSites
= CallSites
.size() *
544 (SiteStartSize
+ SiteLengthSize
+ LandingPadSize
);
545 for (unsigned i
= 0, e
= CallSites
.size(); i
< e
; ++i
) {
546 SizeSites
+= TargetAsmInfo::getULEB128Size(CallSites
[i
].Action
);
547 if (TAI
->getExceptionHandlingType() == ExceptionHandling::SjLj
)
548 SizeSites
+= TargetAsmInfo::getULEB128Size(i
);
549 // FIXME: 'i' above should be the landing pad index
552 const unsigned TypeInfoSize
= TD
->getPointerSize(); // DW_EH_PE_absptr
553 unsigned SizeTypes
= TypeInfos
.size() * TypeInfoSize
;
555 unsigned TypeOffset
= sizeof(int8_t) + // Call site format
556 TargetAsmInfo::getULEB128Size(SizeSites
) + // Call-site table length
557 SizeSites
+ SizeActions
+ SizeTypes
;
559 unsigned TotalSize
= sizeof(int8_t) + // LPStart format
560 sizeof(int8_t) + // TType format
562 TargetAsmInfo::getULEB128Size(TypeOffset
) : 0) + // TType base offset
565 unsigned SizeAlign
= (4 - TotalSize
) & 3;
567 // Begin the exception table.
568 const MCSection
*LSDASection
= Asm
->getObjFileLowering().getLSDASection();
569 Asm
->SwitchToSection(LSDASection
);
570 Asm
->EmitAlignment(2, 0, 0, false);
571 O
<< "GCC_except_table" << SubprogramCount
<< ":\n";
573 for (unsigned i
= 0; i
!= SizeAlign
; ++i
) {
578 EmitLabel("exception", SubprogramCount
);
579 if (TAI
->getExceptionHandlingType() == ExceptionHandling::SjLj
) {
580 std::string SjLjName
= "_lsda_";
581 SjLjName
+= MF
->getFunction()->getName().str();
582 EmitLabel(SjLjName
.c_str(), 0);
586 Asm
->EmitInt8(dwarf::DW_EH_PE_omit
);
587 Asm
->EOL("LPStart format (DW_EH_PE_omit)");
590 if (TypeInfos
.empty() && FilterIds
.empty()) {
591 // If there are no typeinfos or filters, there is nothing to emit, optimize
592 // by specifying the "omit" encoding.
593 Asm
->EmitInt8(dwarf::DW_EH_PE_omit
);
594 Asm
->EOL("TType format (DW_EH_PE_omit)");
596 // Okay, we have actual filters or typeinfos to emit. As such, we need to
597 // pick a type encoding for them. We're about to emit a list of pointers to
598 // typeinfo objects at the end of the LSDA. However, unless we're in static
599 // mode, this reference will require a relocation by the dynamic linker.
601 // Because of this, we have a couple of options:
602 // 1) If we are in -static mode, we can always use an absolute reference
603 // from the LSDA, because the static linker will resolve it.
604 // 2) Otherwise, if the LSDA section is writable, we can output the direct
605 // reference to the typeinfo and allow the dynamic linker to relocate
606 // it. Since it is in a writable section, the dynamic linker won't
608 // 3) Finally, if we're in PIC mode and the LDSA section isn't writable,
609 // we need to use some form of indirection. For example, on Darwin,
610 // we can output a statically-relocatable reference to a dyld stub. The
611 // offset to the stub is constant, but the contents are in a section
612 // that is updated by the dynamic linker. This is easy enough, but we
613 // need to tell the personality function of the unwinder to indirect
614 // through the dyld stub.
616 // FIXME: When this is actually implemented, we'll have to emit the stubs
617 // somewhere. This predicate should be moved to a shared location that is
618 // in target-independent code.
620 if (LSDASection
->isWritable() ||
621 Asm
->TM
.getRelocationModel() == Reloc::Static
) {
622 Asm
->EmitInt8(DW_EH_PE_absptr
);
623 Asm
->EOL("TType format (DW_EH_PE_absptr)");
625 Asm
->EmitInt8(DW_EH_PE_pcrel
| DW_EH_PE_indirect
| DW_EH_PE_sdata4
);
626 Asm
->EOL("TType format (DW_EH_PE_pcrel | DW_EH_PE_indirect"
627 " | DW_EH_PE_sdata4)");
629 Asm
->EmitULEB128Bytes(TypeOffset
);
630 Asm
->EOL("TType base offset");
633 // For SjLj exceptions, if there is no TypeInfo, then we just explicitly
634 // say that we're omitting that bit.
635 // FIXME: does this apply to Dwarf also? The above #if 0 implies yes?
637 Asm
->EmitInt8(dwarf::DW_EH_PE_omit
);
638 Asm
->EOL("TType format (DW_EH_PE_omit)");
640 Asm
->EmitInt8(dwarf::DW_EH_PE_absptr
);
641 Asm
->EOL("TType format (DW_EH_PE_absptr)");
642 Asm
->EmitULEB128Bytes(TypeOffset
);
643 Asm
->EOL("TType base offset");
647 // SjLj Exception handilng
648 if (TAI
->getExceptionHandlingType() == ExceptionHandling::SjLj
) {
649 Asm
->EmitInt8(dwarf::DW_EH_PE_udata4
);
650 Asm
->EOL("Call site format (DW_EH_PE_udata4)");
651 Asm
->EmitULEB128Bytes(SizeSites
);
652 Asm
->EOL("Call-site table length");
655 assert(MF
->getCallSiteCount() == CallSites
.size());
657 // Emit the landing pad site information.
658 // SjLj handling assigned the call site indices in the front end, so
659 // we need to make sure the table here lines up with that. That's pretty
660 // horrible, and should be fixed ASAP to do that stuff in the back end
662 std::map
<unsigned, CallSiteEntry
*>::const_iterator I
, E
;
663 I
= CallSiteIndexMap
.begin();
664 E
= CallSiteIndexMap
.end();
665 for (unsigned CurrIdx
= 1; I
!= E
; ++I
) {
667 assert(CurrIdx
<= I
->first
);
668 // Fill in any gaps in the table
669 while (CurrIdx
++ < I
->first
) {
670 Asm
->EmitULEB128Bytes(0);
671 Asm
->EOL("Filler landing pad");
672 Asm
->EmitULEB128Bytes(0);
673 Asm
->EOL("Filler action");
675 const CallSiteEntry
&S
= *(I
->second
);
676 Asm
->EmitULEB128Bytes(I
->first
- 1);
677 Asm
->EOL("Landing pad");
678 Asm
->EmitULEB128Bytes(S
.Action
);
682 // DWARF Exception handling
683 assert(TAI
->getExceptionHandlingType() == ExceptionHandling::Dwarf
);
685 Asm
->EmitInt8(dwarf::DW_EH_PE_udata4
);
686 Asm
->EOL("Call site format (DW_EH_PE_udata4)");
687 Asm
->EmitULEB128Bytes(SizeSites
);
688 Asm
->EOL("Call-site table length");
690 // Emit the landing pad site information.
691 for (SmallVectorImpl
<CallSiteEntry
>::const_iterator
692 I
= CallSites
.begin(), E
= CallSites
.end(); I
!= E
; ++I
) {
693 const CallSiteEntry
&S
= *I
;
694 const char *BeginTag
;
695 unsigned BeginNumber
;
698 BeginTag
= "eh_func_begin";
699 BeginNumber
= SubprogramCount
;
702 BeginNumber
= S
.BeginLabel
;
705 EmitSectionOffset(BeginTag
, "eh_func_begin", BeginNumber
, SubprogramCount
,
707 Asm
->EOL("Region start");
710 EmitDifference("eh_func_end", SubprogramCount
, BeginTag
, BeginNumber
,
713 EmitDifference("label", S
.EndLabel
, BeginTag
, BeginNumber
, true);
715 Asm
->EOL("Region length");
720 EmitSectionOffset("label", "eh_func_begin", S
.PadLabel
, SubprogramCount
,
723 Asm
->EOL("Landing pad");
725 Asm
->EmitULEB128Bytes(S
.Action
);
731 for (SmallVectorImpl
<ActionEntry
>::const_iterator
732 I
= Actions
.begin(), E
= Actions
.end(); I
!= E
; ++I
) {
733 const ActionEntry
&Action
= *I
;
734 Asm
->EmitSLEB128Bytes(Action
.ValueForTypeID
);
735 Asm
->EOL("TypeInfo index");
736 Asm
->EmitSLEB128Bytes(Action
.NextAction
);
737 Asm
->EOL("Next action");
740 // Emit the type ids.
741 for (std::vector
<GlobalVariable
*>::const_reverse_iterator
742 I
= TypeInfos
.rbegin(), E
= TypeInfos
.rend(); I
!= E
; ++I
) {
743 GlobalVariable
*GV
= *I
;
748 O
<< Asm
->getGlobalLinkName(GV
, GLN
);
753 Asm
->EOL("TypeInfo");
756 // Emit the filter typeids.
757 for (std::vector
<unsigned>::const_iterator
758 I
= FilterIds
.begin(), E
= FilterIds
.end(); I
< E
; ++I
) {
759 unsigned TypeID
= *I
;
760 Asm
->EmitULEB128Bytes(TypeID
);
761 Asm
->EOL("Filter TypeInfo index");
764 Asm
->EmitAlignment(2, 0, 0, false);
767 /// EndModule - Emit all exception information that should come after the
769 void DwarfException::EndModule() {
770 if (TAI
->getExceptionHandlingType() != ExceptionHandling::Dwarf
)
772 if (TimePassesIsEnabled
)
773 ExceptionTimer
->startTimer();
775 if (shouldEmitMovesModule
|| shouldEmitTableModule
) {
776 const std::vector
<Function
*> Personalities
= MMI
->getPersonalities();
777 for (unsigned i
= 0; i
< Personalities
.size(); ++i
)
778 EmitCommonEHFrame(Personalities
[i
], i
);
780 for (std::vector
<FunctionEHFrameInfo
>::iterator I
= EHFrames
.begin(),
781 E
= EHFrames
.end(); I
!= E
; ++I
)
785 if (TimePassesIsEnabled
)
786 ExceptionTimer
->stopTimer();
789 /// BeginFunction - Gather pre-function exception information. Assumes being
790 /// emitted immediately after the function entry point.
791 void DwarfException::BeginFunction(MachineFunction
*MF
) {
792 if (TimePassesIsEnabled
)
793 ExceptionTimer
->startTimer();
796 shouldEmitTable
= shouldEmitMoves
= false;
798 if (MMI
&& TAI
->doesSupportExceptionHandling()) {
799 // Map all labels and get rid of any dead landing pads.
800 MMI
->TidyLandingPads();
802 // If any landing pads survive, we need an EH table.
803 if (MMI
->getLandingPads().size())
804 shouldEmitTable
= true;
806 // See if we need frame move info.
807 if (!MF
->getFunction()->doesNotThrow() || UnwindTablesMandatory
)
808 shouldEmitMoves
= true;
810 if (shouldEmitMoves
|| shouldEmitTable
)
811 // Assumes in correct section after the entry point.
812 EmitLabel("eh_func_begin", ++SubprogramCount
);
815 shouldEmitTableModule
|= shouldEmitTable
;
816 shouldEmitMovesModule
|= shouldEmitMoves
;
818 if (TimePassesIsEnabled
)
819 ExceptionTimer
->stopTimer();
822 /// EndFunction - Gather and emit post-function exception information.
824 void DwarfException::EndFunction() {
825 if (TimePassesIsEnabled
)
826 ExceptionTimer
->startTimer();
828 if (shouldEmitMoves
|| shouldEmitTable
) {
829 EmitLabel("eh_func_end", SubprogramCount
);
830 EmitExceptionTable();
832 // Save EH frame information
834 FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF
),
836 MMI
->getPersonalityIndex(),
837 MF
->getFrameInfo()->hasCalls(),
838 !MMI
->getLandingPads().empty(),
839 MMI
->getFrameMoves(),
843 if (TimePassesIsEnabled
)
844 ExceptionTimer
->stopTimer();