Skip to content

Commit d09b416

Browse files
committed
Use assembler expressions to lay out the EH LSDA.
Rely on the assembler to finalize the layout of the DWARF/Itanium exception-handling LSDA. Rather than calculate the exact size of each thing in the LSDA, use assembler directives: To emit the offset to the TTBase label: .uleb128 .Lttbase0-.Lttbaseref0 .Lttbaseref0: To emit the size of the call site table: .uleb128 .Lcst_end0-.Lcst_begin0 .Lcst_begin0: ... call site table entries ... .Lcst_end0: To align the type info table: ... action table ... .balign 4 .long _ZTIi .long _ZTIl .Lttbase0: Using assembler directives simplifies the compiler and allows switching the encoding of offsets in the call site table from udata4 to uleb128 for a large code size savings. (This commit does not change the encoding.) The combination of the uleb128 followed by a balign creates an unfortunate dependency cycle that the assembler must sometimes resolve either by padding an LEB or by inserting zero padding before the type table. See PR35809 or GNU as bug 4029. Patch by Ryan Prichard! llvm-svn: 324749
1 parent e7da136 commit d09b416

16 files changed

+122
-142
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,10 @@ class AsmPrinter : public MachineFunctionPass {
458458
void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
459459
unsigned Size) const;
460460

461+
/// Emit something like ".uleb128 Hi-Lo".
462+
void EmitLabelDifferenceAsULEB128(const MCSymbol *Hi,
463+
const MCSymbol *Lo) const;
464+
461465
/// Emit something like ".long Label+Offset" where the size in bytes of the
462466
/// directive is specified by Size and Label specifies the label. This
463467
/// implicitly uses .set if it is available.
@@ -481,11 +485,6 @@ class AsmPrinter : public MachineFunctionPass {
481485
/// Emit the specified unsigned leb128 value.
482486
void EmitULEB128(uint64_t Value, const char *Desc = nullptr) const;
483487

484-
/// Emit the specified unsigned leb128 value padded to a specific number
485-
/// bytes
486-
void EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
487-
const char *Desc = nullptr) const;
488-
489488
/// Emit a .byte 42 directive that corresponds to an encoding. If verbose
490489
/// assembly output is enabled, we output comments describing the encoding.
491490
/// Desc is a string saying what the encoding is specifying (e.g. "LSDA").

llvm/include/llvm/MC/MCObjectStreamer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ class MCObjectStreamer : public MCStreamer {
179179
void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
180180
unsigned Size) override;
181181

182+
void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
183+
const MCSymbol *Lo) override;
184+
182185
bool mayHaveInstructions(MCSection &Sec) const override;
183186
};
184187

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,6 @@ class MCStreamer {
609609
/// pass in a MCExpr for constant integers.
610610
void EmitULEB128IntValue(uint64_t Value);
611611

612-
/// \brief Like EmitULEB128Value but pads the output to specific number of
613-
/// bytes.
614-
void EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo);
615-
616612
/// \brief Special case of EmitSLEB128Value that avoids the client having to
617613
/// pass in a MCExpr for constant integers.
618614
void EmitSLEB128IntValue(int64_t Value);
@@ -828,6 +824,10 @@ class MCStreamer {
828824
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
829825
unsigned Size);
830826

827+
/// Emit the absolute difference between two symbols encoded with ULEB128.
828+
virtual void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
829+
const MCSymbol *Lo);
830+
831831
virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID);
832832
virtual void EmitCFISections(bool EH, bool Debug);
833833
void EmitCFIStartProc(bool IsSimple);

llvm/lib/CodeGen/AsmPrinter/ARMException.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ void ARMException::endFunction(const MachineFunction *MF) {
9191
ATS.emitFnEnd();
9292
}
9393

94-
void ARMException::emitTypeInfos(unsigned TTypeEncoding) {
94+
void ARMException::emitTypeInfos(unsigned TTypeEncoding,
95+
MCSymbol *TTBaseLabel) {
9596
const MachineFunction *MF = Asm->MF;
9697
const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
9798
const std::vector<unsigned> &FilterIds = MF->getFilterIds();
@@ -112,6 +113,8 @@ void ARMException::emitTypeInfos(unsigned TTypeEncoding) {
112113
Asm->EmitTTypeReference(GV, TTypeEncoding);
113114
}
114115

116+
Asm->OutStreamer->EmitLabel(TTBaseLabel);
117+
115118
// Emit the Exception Specifications.
116119
if (VerboseAsm && !FilterIds.empty()) {
117120
Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");

llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,19 @@ void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
4343
OutStreamer->EmitSLEB128IntValue(Value);
4444
}
4545

46-
/// EmitULEB128 - emit the specified unsigned leb128 value.
47-
void AsmPrinter::EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
48-
const char *Desc) const {
49-
if (isVerbose() && Desc)
50-
OutStreamer->AddComment(Desc);
51-
52-
OutStreamer->EmitPaddedULEB128IntValue(Value, PadTo);
53-
}
54-
5546
void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc) const {
5647
if (isVerbose() && Desc)
5748
OutStreamer->AddComment(Desc);
5849

5950
OutStreamer->EmitULEB128IntValue(Value);
6051
}
6152

53+
/// Emit something like ".uleb128 Hi-Lo".
54+
void AsmPrinter::EmitLabelDifferenceAsULEB128(const MCSymbol *Hi,
55+
const MCSymbol *Lo) const {
56+
OutStreamer->emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
57+
}
58+
6259
static const char *DecodeDWARFEncoding(unsigned Encoding) {
6360
switch (Encoding) {
6461
case dwarf::DW_EH_PE_absptr:
@@ -67,6 +64,10 @@ static const char *DecodeDWARFEncoding(unsigned Encoding) {
6764
return "omit";
6865
case dwarf::DW_EH_PE_pcrel:
6966
return "pcrel";
67+
case dwarf::DW_EH_PE_uleb128:
68+
return "uleb128";
69+
case dwarf::DW_EH_PE_sleb128:
70+
return "sleb128";
7071
case dwarf::DW_EH_PE_udata4:
7172
return "udata4";
7273
case dwarf::DW_EH_PE_udata8:

llvm/lib/CodeGen/AsmPrinter/DwarfException.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class LLVM_LIBRARY_VISIBILITY DwarfCFIException : public DwarfCFIExceptionBase {
7070
};
7171

7272
class LLVM_LIBRARY_VISIBILITY ARMException : public DwarfCFIExceptionBase {
73-
void emitTypeInfos(unsigned TTypeEncoding) override;
73+
void emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) override;
7474
ARMTargetStreamer &getTargetStreamer();
7575

7676
public:

llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp

Lines changed: 32 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ unsigned EHStreamer::sharedTypeIDs(const LandingPadInfo *L,
5858

5959
/// Compute the actions table and gather the first action index for each landing
6060
/// pad site.
61-
unsigned EHStreamer::
62-
computeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
63-
SmallVectorImpl<ActionEntry> &Actions,
64-
SmallVectorImpl<unsigned> &FirstActions) {
61+
void EHStreamer::computeActionsTable(
62+
const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
63+
SmallVectorImpl<ActionEntry> &Actions,
64+
SmallVectorImpl<unsigned> &FirstActions) {
6565
// The action table follows the call-site table in the LSDA. The individual
6666
// records are of two types:
6767
//
@@ -161,8 +161,6 @@ computeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
161161

162162
PrevLPI = LPI;
163163
}
164-
165-
return SizeActions;
166164
}
167165

168166
/// Return `true' if this is a call to a function marked `nounwind'. Return
@@ -369,47 +367,23 @@ void EHStreamer::emitExceptionTable() {
369367
// landing pad site.
370368
SmallVector<ActionEntry, 32> Actions;
371369
SmallVector<unsigned, 64> FirstActions;
372-
unsigned SizeActions =
373-
computeActionsTable(LandingPads, Actions, FirstActions);
370+
computeActionsTable(LandingPads, Actions, FirstActions);
374371

375372
// Compute the call-site table.
376373
SmallVector<CallSiteEntry, 64> CallSites;
377374
computeCallSiteTable(CallSites, LandingPads, FirstActions);
378375

379-
// Final tallies.
380-
381-
// Call sites.
382376
bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
383377
bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true;
384378

385-
unsigned CallSiteTableLength;
386-
if (IsSJLJ)
387-
CallSiteTableLength = 0;
388-
else {
389-
unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4
390-
unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4
391-
unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4
392-
CallSiteTableLength =
393-
CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize);
394-
}
395-
396-
for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
397-
CallSiteTableLength += getULEB128Size(CallSites[i].Action);
398-
if (IsSJLJ)
399-
CallSiteTableLength += getULEB128Size(i);
400-
}
401-
402379
// Type infos.
403380
MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection();
404381
unsigned TTypeEncoding;
405-
unsigned TypeFormatSize;
406382

407383
if (!HaveTTData) {
408384
// For SjLj exceptions, if there is no TypeInfo, then we just explicitly say
409385
// that we're omitting that bit.
410386
TTypeEncoding = dwarf::DW_EH_PE_omit;
411-
// dwarf::DW_EH_PE_absptr
412-
TypeFormatSize = Asm->getDataLayout().getPointerSize();
413387
} else {
414388
// Okay, we have actual filters or typeinfos to emit. As such, we need to
415389
// pick a type encoding for them. We're about to emit a list of pointers to
@@ -439,7 +413,6 @@ void EHStreamer::emitExceptionTable() {
439413
// in target-independent code.
440414
//
441415
TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding();
442-
TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding);
443416
}
444417

445418
// Begin the exception table.
@@ -460,64 +433,35 @@ void EHStreamer::emitExceptionTable() {
460433
Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
461434
Asm->EmitEncodingByte(TTypeEncoding, "@TType");
462435

463-
// The type infos need to be aligned. GCC does this by inserting padding just
464-
// before the type infos. However, this changes the size of the exception
465-
// table, so you need to take this into account when you output the exception
466-
// table size. However, the size is output using a variable length encoding.
467-
// So by increasing the size by inserting padding, you may increase the number
468-
// of bytes used for writing the size. If it increases, say by one byte, then
469-
// you now need to output one less byte of padding to get the type infos
470-
// aligned. However this decreases the size of the exception table. This
471-
// changes the value you have to output for the exception table size. Due to
472-
// the variable length encoding, the number of bytes used for writing the
473-
// length may decrease. If so, you then have to increase the amount of
474-
// padding. And so on. If you look carefully at the GCC code you will see that
475-
// it indeed does this in a loop, going on and on until the values stabilize.
476-
// We chose another solution: don't output padding inside the table like GCC
477-
// does, instead output it before the table.
478-
unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
479-
unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength);
480-
unsigned TTypeBaseOffset =
481-
sizeof(int8_t) + // Call site format
482-
CallSiteTableLengthSize + // Call site table length size
483-
CallSiteTableLength + // Call site table length
484-
SizeActions + // Actions size
485-
SizeTypes;
486-
unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset);
487-
unsigned TotalSize =
488-
sizeof(int8_t) + // LPStart format
489-
sizeof(int8_t) + // TType format
490-
(HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size
491-
TTypeBaseOffset; // TType base offset
492-
unsigned PadBytes = (4 - TotalSize) & 3;
493-
436+
MCSymbol *TTBaseLabel = nullptr;
494437
if (HaveTTData) {
495-
// Account for any extra padding that will be added to the call site table
496-
// length.
497-
Asm->EmitPaddedULEB128(TTypeBaseOffset, TTypeBaseOffsetSize + PadBytes,
498-
"@TType base offset");
499-
PadBytes = 0;
438+
// N.B.: There is a dependency loop between the size of the TTBase uleb128
439+
// here and the amount of padding before the aligned type table. The
440+
// assembler must sometimes pad this uleb128 or insert extra padding before
441+
// the type table. See PR35809 or GNU as bug 4029.
442+
MCSymbol *TTBaseRefLabel = Asm->createTempSymbol("ttbaseref");
443+
TTBaseLabel = Asm->createTempSymbol("ttbase");
444+
Asm->EmitLabelDifferenceAsULEB128(TTBaseLabel, TTBaseRefLabel);
445+
Asm->OutStreamer->EmitLabel(TTBaseRefLabel);
500446
}
501447

502448
bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
503449

450+
// Emit the landing pad call site table.
451+
MCSymbol *CstBeginLabel = Asm->createTempSymbol("cst_begin");
452+
MCSymbol *CstEndLabel = Asm->createTempSymbol("cst_end");
453+
Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
454+
Asm->EmitLabelDifferenceAsULEB128(CstEndLabel, CstBeginLabel);
455+
Asm->OutStreamer->EmitLabel(CstBeginLabel);
456+
504457
// SjLj Exception handling
505458
if (IsSJLJ) {
506-
Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
507-
508-
// Add extra padding if it wasn't added to the TType base offset.
509-
Asm->EmitPaddedULEB128(CallSiteTableLength,
510-
CallSiteTableLengthSize + PadBytes,
511-
"Call site table length");
512-
513-
// Emit the landing pad site information.
514459
unsigned idx = 0;
515460
for (SmallVectorImpl<CallSiteEntry>::const_iterator
516461
I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) {
517462
const CallSiteEntry &S = *I;
518463

519-
// Offset of the landing pad, counted in 16-byte bundles relative to the
520-
// @LPStart address.
464+
// Index of the call site entry.
521465
if (VerboseAsm) {
522466
Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<");
523467
Asm->OutStreamer->AddComment(" On exception at call site "+Twine(idx));
@@ -557,14 +501,6 @@ void EHStreamer::emitExceptionTable() {
557501
// A missing entry in the call-site table indicates that a call is not
558502
// supposed to throw.
559503

560-
// Emit the landing pad call site table.
561-
Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
562-
563-
// Add extra padding if it wasn't added to the TType base offset.
564-
Asm->EmitPaddedULEB128(CallSiteTableLength,
565-
CallSiteTableLengthSize + PadBytes,
566-
"Call site table length");
567-
568504
unsigned Entry = 0;
569505
for (SmallVectorImpl<CallSiteEntry>::const_iterator
570506
I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
@@ -579,9 +515,7 @@ void EHStreamer::emitExceptionTable() {
579515
if (!EndLabel)
580516
EndLabel = Asm->getFunctionEnd();
581517

582-
// Offset of the call site relative to the previous call site, counted in
583-
// number of 16-byte bundles. The first call site is counted relative to
584-
// the start of the procedure fragment.
518+
// Offset of the call site relative to the start of the procedure.
585519
if (VerboseAsm)
586520
Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + " <<");
587521
Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
@@ -591,8 +525,7 @@ void EHStreamer::emitExceptionTable() {
591525
EndLabel->getName());
592526
Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
593527

594-
// Offset of the landing pad, counted in 16-byte bundles relative to the
595-
// @LPStart address.
528+
// Offset of the landing pad relative to the start of the procedure.
596529
if (!S.LPad) {
597530
if (VerboseAsm)
598531
Asm->OutStreamer->AddComment(" has no landing pad");
@@ -617,6 +550,7 @@ void EHStreamer::emitExceptionTable() {
617550
Asm->EmitULEB128(S.Action);
618551
}
619552
}
553+
Asm->OutStreamer->EmitLabel(CstEndLabel);
620554

621555
// Emit the Action Table.
622556
int Entry = 0;
@@ -660,12 +594,15 @@ void EHStreamer::emitExceptionTable() {
660594
Asm->EmitSLEB128(Action.NextAction);
661595
}
662596

663-
emitTypeInfos(TTypeEncoding);
597+
if (HaveTTData) {
598+
Asm->EmitAlignment(2);
599+
emitTypeInfos(TTypeEncoding, TTBaseLabel);
600+
}
664601

665602
Asm->EmitAlignment(2);
666603
}
667604

668-
void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) {
605+
void EHStreamer::emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) {
669606
const MachineFunction *MF = Asm->MF;
670607
const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
671608
const std::vector<unsigned> &FilterIds = MF->getFilterIds();
@@ -687,6 +624,8 @@ void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) {
687624
Asm->EmitTTypeReference(GV, TTypeEncoding);
688625
}
689626

627+
Asm->OutStreamer->EmitLabel(TTBaseLabel);
628+
690629
// Emit the Exception Specifications.
691630
if (VerboseAsm && !FilterIds.empty()) {
692631
Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");

llvm/lib/CodeGen/AsmPrinter/EHStreamer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ class LLVM_LIBRARY_VISIBILITY EHStreamer : public AsmPrinterHandler {
7272

7373
/// Compute the actions table and gather the first action index for each
7474
/// landing pad site.
75-
unsigned computeActionsTable(const SmallVectorImpl<const LandingPadInfo*>&LPs,
76-
SmallVectorImpl<ActionEntry> &Actions,
77-
SmallVectorImpl<unsigned> &FirstActions);
75+
void computeActionsTable(const SmallVectorImpl<const LandingPadInfo *> &LPs,
76+
SmallVectorImpl<ActionEntry> &Actions,
77+
SmallVectorImpl<unsigned> &FirstActions);
7878

7979
void computePadMap(const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
8080
RangeMapType &PadMap);
@@ -110,7 +110,7 @@ class LLVM_LIBRARY_VISIBILITY EHStreamer : public AsmPrinterHandler {
110110
/// catches in the function. This tables is reversed indexed base 1.
111111
void emitExceptionTable();
112112

113-
virtual void emitTypeInfos(unsigned TTypeEncoding);
113+
virtual void emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel);
114114

115115
// Helpers for identifying what kind of clause an EH typeid or selector
116116
// corresponds to. Negative selectors are for filter clauses, the zero

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
910910
EmitULEB128IntValue(IntValue);
911911
return;
912912
}
913-
OS << ".uleb128 ";
913+
OS << "\t.uleb128 ";
914914
Value->print(OS, MAI);
915915
EmitEOL();
916916
}
@@ -921,7 +921,7 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
921921
EmitSLEB128IntValue(IntValue);
922922
return;
923923
}
924-
OS << ".sleb128 ";
924+
OS << "\t.sleb128 ";
925925
Value->print(OS, MAI);
926926
EmitEOL();
927927
}

0 commit comments

Comments
 (0)