[BOLT] Use new assembler directives for EH table emission (#116294)

When emitting C++ exception tables (LSDAs), BOLT used to estimate the
size of the tables beforehand. This implementation was necessary as the
assembler/streamer lacked the emitULEB128IntValue() functionality.

As I plan to introduce [u|s]uleb128-encoded exception tables in BOLT,
now is a perfect time to switch to the new API and eliminate the need
to pre-compute the size of the tables.
This commit is contained in:
Maksim Panchenko
2024-11-17 12:40:07 -08:00
committed by GitHub
parent c4eeef32d5
commit 93a4244523

View File

@@ -906,17 +906,6 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
if (Sites.empty())
return;
// Calculate callsite table size. Size of each callsite entry is:
//
// sizeof(start) + sizeof(length) + sizeof(LP) + sizeof(uleb128(action))
//
// or
//
// sizeof(dwarf::DW_EH_PE_data4) * 3 + sizeof(uleb128(action))
uint64_t CallSiteTableLength = llvm::size(Sites) * 4 * 3;
for (const auto &FragmentCallSite : Sites)
CallSiteTableLength += getULEB128Size(FragmentCallSite.second.Action);
Streamer.switchSection(BC.MOFI->getLSDASection());
const unsigned TTypeEncoding = BF.getLSDATypeEncoding();
@@ -975,36 +964,24 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
Streamer.emitIntValue(TTypeEncoding, 1); // TType format
// See the comment in EHStreamer::emitExceptionTable() on to use
// uleb128 encoding (which can use variable number of bytes to encode the same
// value) to ensure type info table is properly aligned at 4 bytes without
// iteratively fixing sizes of the tables.
unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength);
unsigned TTypeBaseOffset =
sizeof(int8_t) + // Call site format
CallSiteTableLengthSize + // Call site table length size
CallSiteTableLength + // Call site table length
BF.getLSDAActionTable().size() + // Actions table size
BF.getLSDATypeTable().size() * TTypeEncodingSize; // Types table size
unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset);
unsigned TotalSize = sizeof(int8_t) + // LPStart format
sizeof(int8_t) + // TType format
TTypeBaseOffsetSize + // TType base offset size
TTypeBaseOffset; // TType base offset
unsigned SizeAlign = (4 - TotalSize) & 3;
if (TTypeEncoding != dwarf::DW_EH_PE_omit)
// Account for any extra padding that will be added to the call site table
// length.
Streamer.emitULEB128IntValue(TTypeBaseOffset,
/*PadTo=*/TTypeBaseOffsetSize + SizeAlign);
MCSymbol *TTBaseLabel = nullptr;
if (TTypeEncoding != dwarf::DW_EH_PE_omit) {
TTBaseLabel = BC.Ctx->createTempSymbol("TTBase");
MCSymbol *TTBaseRefLabel = BC.Ctx->createTempSymbol("TTBaseRef");
Streamer.emitAbsoluteSymbolDiffAsULEB128(TTBaseLabel, TTBaseRefLabel);
Streamer.emitLabel(TTBaseRefLabel);
}
// Emit the landing pad call site table. We use signed data4 since we can emit
// a landing pad in a different part of the split function that could appear
// earlier in the address space than LPStart.
Streamer.emitIntValue(dwarf::DW_EH_PE_sdata4, 1);
Streamer.emitULEB128IntValue(CallSiteTableLength);
MCSymbol *CSTStartLabel = BC.Ctx->createTempSymbol("CSTStart");
MCSymbol *CSTEndLabel = BC.Ctx->createTempSymbol("CSTEnd");
Streamer.emitAbsoluteSymbolDiffAsULEB128(CSTEndLabel, CSTStartLabel);
Streamer.emitLabel(CSTStartLabel);
for (const auto &FragmentCallSite : Sites) {
const BinaryFunction::CallSite &CallSite = FragmentCallSite.second;
const MCSymbol *BeginLabel = CallSite.Start;
@@ -1020,6 +997,7 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
emitLandingPad(CallSite.LP);
Streamer.emitULEB128IntValue(CallSite.Action);
}
Streamer.emitLabel(CSTEndLabel);
// Write out action, type, and type index tables at the end.
//
@@ -1038,6 +1016,8 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
assert(TypeTable.size() == BF.getLSDATypeTable().size() &&
"indirect type table size mismatch");
Streamer.emitValueToAlignment(Align(TTypeAlignment));
for (int Index = TypeTable.size() - 1; Index >= 0; --Index) {
const uint64_t TypeAddress = TypeTable[Index];
switch (TTypeEncoding & 0x70) {
@@ -1063,6 +1043,10 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) {
}
}
}
if (TTypeEncoding != dwarf::DW_EH_PE_omit)
Streamer.emitLabel(TTBaseLabel);
for (uint8_t const &Byte : BF.getLSDATypeIndexTable())
Streamer.emitIntValue(Byte, 1);
}