diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2018-02-09 17:00:25 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2018-02-09 17:00:25 +0000 |
commit | d09b416943fec535f73950b0954e0fcd17719a75 (patch) | |
tree | 9b193a55c6d4e422a146d77f11ac5a0ecf470dfe /llvm/lib/MC | |
parent | e7da136a74ac9073528327aa8364bad97156ba51 (diff) | |
download | bcm5719-llvm-d09b416943fec535f73950b0954e0fcd17719a75.tar.gz bcm5719-llvm-d09b416943fec535f73950b0954e0fcd17719a75.zip |
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
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 27 | ||||
-rw-r--r-- | llvm/lib/MC/MCStreamer.cpp | 22 |
3 files changed, 38 insertions, 15 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 4e8dcf61491..927c1889c88 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -910,7 +910,7 @@ void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { EmitULEB128IntValue(IntValue); return; } - OS << ".uleb128 "; + OS << "\t.uleb128 "; Value->print(OS, MAI); EmitEOL(); } @@ -921,7 +921,7 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { EmitSLEB128IntValue(IntValue); return; } - OS << ".sleb128 "; + OS << "\t.sleb128 "; Value->print(OS, MAI); EmitEOL(); } diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 230c02188a6..9c69a5a962d 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -51,17 +51,34 @@ void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) { PendingLabels.clear(); } +// As a compile-time optimization, avoid allocating and evaluating an MCExpr +// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment. +static Optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi, + const MCSymbol *Lo) { + if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() || + Hi->isVariable() || Lo->isVariable()) + return None; + + return Hi->getOffset() - Lo->getOffset(); +} + void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) { - // If not assigned to the same (valid) fragment, fallback. - if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() || - Hi->isVariable() || Lo->isVariable()) { - MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size); + if (Optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) { + EmitIntValue(*Diff, Size); return; } + MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size); +} - EmitIntValue(Hi->getOffset() - Lo->getOffset(), Size); +void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, + const MCSymbol *Lo) { + if (Optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) { + EmitULEB128IntValue(*Diff); + return; + } + MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo); } void MCObjectStreamer::reset() { diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index 9dcd1e9101c..bc9c93f144e 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -120,20 +120,16 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) { EmitBytes(StringRef(buf, Size)); } -/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the +/// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. -void MCStreamer::EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo) { +void MCStreamer::EmitULEB128IntValue(uint64_t Value) { SmallString<128> Tmp; raw_svector_ostream OSE(Tmp); - encodeULEB128(Value, OSE, PadTo); + encodeULEB128(Value, OSE); EmitBytes(OSE.str()); } -void MCStreamer::EmitULEB128IntValue(uint64_t Value) { - EmitPaddedULEB128IntValue(Value, 0); -} - -/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the +/// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. void MCStreamer::EmitSLEB128IntValue(int64_t Value) { SmallString<128> Tmp; @@ -902,6 +898,16 @@ void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, EmitSymbolValue(SetLabel, Size); } +void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, + const MCSymbol *Lo) { + // Get the Hi-Lo expression. + const MCExpr *Diff = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context), + MCSymbolRefExpr::create(Lo, Context), Context); + + EmitULEB128Value(Diff); +} + void MCStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {} void MCStreamer::EmitThumbFunc(MCSymbol *Func) {} void MCStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} |