diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 45d8676b4d2..893340e932b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -619,9 +619,11 @@ void DwarfException::EmitExceptionTable() { // Type infos. const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); unsigned TTypeFormat; + unsigned TypeFormatSize; if (!HaveTTData) { TTypeFormat = dwarf::DW_EH_PE_omit; + TypeFormatSize = SizeOfEncodedValue(dwarf::DW_EH_PE_absptr); } else { // Okay, we have actual filters or typeinfos to emit. As such, we need to // pick a type encoding for them. We're about to emit a list of pointers to @@ -653,6 +655,8 @@ void DwarfException::EmitExceptionTable() { else TTypeFormat = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + + TypeFormatSize = SizeOfEncodedValue(TTypeFormat); } // Begin the exception table. @@ -660,6 +664,38 @@ void DwarfException::EmitExceptionTable() { Asm->EmitAlignment(2, 0, 0, false); O << "GCC_except_table" << SubprogramCount << ":\n"; + + // The type infos need to be aligned. GCC does this by inserting padding just + // before the type infos. However, this changes the size of the exception + // table, so you need to take this into account when you output the exception + // table size. However, the size is output using a variable length encoding. + // So by increasing the size by inserting padding, you may increase the number + // of bytes used for writing the size. If it increases, say by one byte, then + // you now need to output one less byte of padding to get the type infos + // aligned. However this decreases the size of the exception table. This + // changes the value you have to output for the exception table size. Due to + // the variable length encoding, the number of bytes used for writing the + // length may decrease. If so, you then have to increase the amount of + // padding. And so on. If you look carefully at the GCC code you will see that + // it indeed does this in a loop, going on and on until the values stabilize. + // We chose another solution: don't output padding inside the table like GCC + // does, instead output it before the table. + unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; + unsigned TyOffset = sizeof(int8_t) + // Call site format + MCAsmInfo::getULEB128Size(SizeSites) + // Call-site table length + SizeSites + SizeActions + SizeTypes; + unsigned TotalSize = sizeof(int8_t) + // LPStart format + sizeof(int8_t) + // TType format + (HaveTTData ? + MCAsmInfo::getULEB128Size(TyOffset) : 0) + // TType base offset + TyOffset; + unsigned SizeAlign = (4 - TotalSize) & 3; + + for (unsigned i = 0; i != SizeAlign; ++i) { + Asm->EmitInt8(0); + Asm->EOL("Padding"); + } + EmitLabel("exception", SubprogramCount); if (IsSJLJ) { @@ -679,29 +715,7 @@ void DwarfException::EmitExceptionTable() { Asm->EOL("@TType format", TTypeFormat); if (HaveTTData) { - unsigned TypeFormatSize = SizeOfEncodedValue(TTypeFormat); - unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; - unsigned BeforeOffset = 2; - unsigned TypeOffset = sizeof(int8_t) + // Call site format - MCAsmInfo::getULEB128Size(SizeSites) + // Call-site table length - SizeSites + SizeActions + SizeTypes; - unsigned Offset = TypeOffset; - unsigned LastOffset = 0; - - while (Offset != LastOffset) { - LastOffset = Offset; - unsigned Size = MCAsmInfo::getULEB128Size(Offset); - unsigned Pad = BeforeOffset + Size + TypeOffset; - - if (Pad % TypeFormatSize) - Pad = TypeFormatSize - (Pad % TypeFormatSize); - else - Pad = 0; - - Offset = TypeOffset + Pad; - } - - Asm->EmitULEB128Bytes(Offset); + Asm->EmitULEB128Bytes(TyOffset); Asm->EOL("@TType base offset"); }