diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -646,6 +646,23 @@ uint32_t *Size = nullptr); }; +// This class provides some helper functions. +class MCDwarfHelper { +public: + /// This helper routine returns an expression of End - Start + IntVal . + static const MCExpr *makeEndMinusStartExpr(MCContext &Ctx, + const MCSymbol &Start, + const MCSymbol &End, int IntVal); + /// This helper routine returns an expression of Start + IntVal . + static const MCExpr *makeStartPlusIntExpr(MCContext &Ctx, + const MCSymbol &Start, int IntVal); + + /// This helper routine emits an absolute Value. + static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size); + + static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr *Expr); +}; + } // end namespace llvm #endif // LLVM_MC_MCDWARF_H diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -1104,6 +1104,14 @@ /// according to the settings. virtual void emitDwarfUnitLength(const MCSymbol *Hi, const MCSymbol *Lo, const Twine &Comment); + + /// Emit a unit length field for debug line section. The actual format, + /// DWARF32 or DWARF64, is chosen according to the settings. The \p Length + /// indicates that the bytes number the streamer writes to the header of debug + /// line section header. + /// FIXME: implement this function in emitDwarfUnitLength. + virtual void emitDwarfLineUnitLength(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned &Length); }; /// Create a dummy machine code streamer, which does nothing. This is useful for diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -130,13 +130,10 @@ .addLineEntry(LineEntry, Section); } -// -// This helper routine returns an expression of End - Start + IntVal . -// -static inline const MCExpr *makeEndMinusStartExpr(MCContext &Ctx, - const MCSymbol &Start, - const MCSymbol &End, - int IntVal) { +const MCExpr *MCDwarfHelper::makeEndMinusStartExpr(MCContext &Ctx, + const MCSymbol &Start, + const MCSymbol &End, + int IntVal) { MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; const MCExpr *Res = MCSymbolRefExpr::create(&End, Variant, Ctx); const MCExpr *RHS = MCSymbolRefExpr::create(&Start, Variant, Ctx); @@ -146,11 +143,9 @@ return Res3; } -// -// This helper routine returns an expression of Start + IntVal . -// -static inline const MCExpr * -makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) { +const MCExpr *MCDwarfHelper::makeStartPlusIntExpr(MCContext &Ctx, + const MCSymbol &Start, + int IntVal) { MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Variant, Ctx); const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx); @@ -307,7 +302,7 @@ LineStr); } -static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) { +const MCExpr *MCDwarfHelper::forceExpAbs(MCStreamer &OS, const MCExpr* Expr) { MCContext &Context = OS.getContext(); assert(!isa(Expr)); if (Context.getAsmInfo()->hasAggressiveSymbolFolding()) @@ -318,7 +313,8 @@ return MCSymbolRefExpr::create(ABS, Context); } -static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) { +void MCDwarfHelper::emitAbsValue(MCStreamer &OS, const MCExpr *Value, + unsigned Size) { const MCExpr *ABS = forceExpAbs(OS, Value); OS.emitValue(ABS, Size); } @@ -341,7 +337,9 @@ size_t Offset = LineStrings.add(Path); if (UseRelocs) { MCContext &Ctx = MCOS->getContext(); - MCOS->emitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize); + MCOS->emitValue( + MCDwarfHelper::makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), + RefSize); } else MCOS->emitIntValue(Offset, RefSize); } @@ -477,20 +475,10 @@ // Create a symbol for the end of the section (to be set when we get there). MCSymbol *LineEndSym = context.createTempSymbol(); - unsigned UnitLengthBytes = - dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat()); + unsigned UnitLengthBytes = 0; unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat()); - if (context.getDwarfFormat() == dwarf::DWARF64) - // Emit DWARF64 mark. - MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64); - - // The length field does not include itself and, in case of the 64-bit DWARF - // format, the DWARF64 mark. - emitAbsValue(*MCOS, - makeEndMinusStartExpr(context, *LineStartSym, *LineEndSym, - UnitLengthBytes), - OffsetSize); + MCOS->emitDwarfLineUnitLength(LineStartSym, LineEndSym, UnitLengthBytes); // Next 2 bytes is the Version. unsigned LineTableVersion = context.getDwarfVersion(); @@ -512,10 +500,11 @@ // Length of the prologue, is the next 4 bytes (8 bytes for DWARF64). This is // actually the length from after the length word, to the end of the prologue. - emitAbsValue(*MCOS, - makeEndMinusStartExpr(context, *LineStartSym, *ProEndSym, - (PreHeaderLengthBytes + OffsetSize)), - OffsetSize); + MCDwarfHelper::emitAbsValue( + *MCOS, + MCDwarfHelper::makeEndMinusStartExpr(context, *LineStartSym, *ProEndSym, + (PreHeaderLengthBytes + OffsetSize)), + OffsetSize); // Parameters of the state machine, are next. MCOS->emitInt8(context.getAsmInfo()->getMinInstAlignment()); @@ -936,10 +925,10 @@ const MCExpr *Addr = MCSymbolRefExpr::create( StartSymbol, MCSymbolRefExpr::VK_None, context); - const MCExpr *Size = - makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0); + const MCExpr *Size = MCDwarfHelper::makeEndMinusStartExpr( + context, *StartSymbol, *EndSymbol, 0); MCOS->emitValue(Addr, AddrSize); - emitAbsValue(*MCOS, Size, AddrSize); + MCDwarfHelper::emitAbsValue(*MCOS, Size, AddrSize); } // And finally the pair of terminating zeros. @@ -976,9 +965,9 @@ // The 4 (8 for DWARF64) byte total length of the information for this // compilation unit, not including the unit length field itself. - const MCExpr *Length = - makeEndMinusStartExpr(context, *InfoStart, *InfoEnd, UnitLengthBytes); - emitAbsValue(*MCOS, Length, OffsetSize); + const MCExpr *Length = MCDwarfHelper::makeEndMinusStartExpr( + context, *InfoStart, *InfoEnd, UnitLengthBytes); + MCDwarfHelper::emitAbsValue(*MCOS, Length, OffsetSize); // The 2 byte DWARF version. MCOS->emitInt16(context.getDwarfVersion()); @@ -1144,8 +1133,8 @@ const MCSymbol *EndSymbol = Sec->getEndSymbol(context); const MCExpr *SectionStartAddr = MCSymbolRefExpr::create( StartSymbol, MCSymbolRefExpr::VK_None, context); - const MCExpr *SectionSize = - makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0); + const MCExpr *SectionSize = MCDwarfHelper::makeEndMinusStartExpr( + context, *StartSymbol, *EndSymbol, 0); MCOS->emitInt8(dwarf::DW_RLE_start_length); MCOS->emitValue(SectionStartAddr, AddrSize); MCOS->emitULEB128Value(SectionSize); @@ -1167,10 +1156,10 @@ MCOS->emitValue(SectionStartAddr, AddrSize); // Emit a range list entry spanning this section. - const MCExpr *SectionSize = - makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0); + const MCExpr *SectionSize = MCDwarfHelper::makeEndMinusStartExpr( + context, *StartSymbol, *EndSymbol, 0); MCOS->emitIntValue(0, AddrSize); - emitAbsValue(*MCOS, SectionSize, AddrSize); + MCDwarfHelper::emitAbsValue(*MCOS, SectionSize, AddrSize); } // Emit end of list entry @@ -1325,7 +1314,7 @@ streamer); unsigned size = getSizeForEncoding(streamer, symbolEncoding); if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH) - emitAbsValue(streamer, v, size); + MCDwarfHelper::emitAbsValue(streamer, v, size); else streamer.emitValue(v, size); } @@ -1563,9 +1552,9 @@ Streamer.emitSymbolValue(Frame.Begin, Size); // Range Length - const MCExpr *Range = - makeEndMinusStartExpr(Context, *Frame.Begin, *Frame.End, 0); - emitAbsValue(Streamer, Range, 4); + const MCExpr *Range = MCDwarfHelper::makeEndMinusStartExpr( + Context, *Frame.Begin, *Frame.End, 0); + MCDwarfHelper::emitAbsValue(Streamer, Range, 4); // Compact Encoding Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); @@ -1621,9 +1610,9 @@ Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64); // Length - const MCExpr *Length = makeEndMinusStartExpr(context, *sectionStart, - *sectionEnd, UnitLengthBytes); - emitAbsValue(Streamer, Length, OffsetSize); + const MCExpr *Length = MCDwarfHelper::makeEndMinusStartExpr( + context, *sectionStart, *sectionEnd, UnitLengthBytes); + MCDwarfHelper::emitAbsValue(Streamer, Length, OffsetSize); // CIE ID uint64_t CIE_ID = @@ -1746,8 +1735,9 @@ Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64); // Length - const MCExpr *Length = makeEndMinusStartExpr(context, *fdeStart, *fdeEnd, 0); - emitAbsValue(Streamer, Length, OffsetSize); + const MCExpr *Length = + MCDwarfHelper::makeEndMinusStartExpr(context, *fdeStart, *fdeEnd, 0); + MCDwarfHelper::emitAbsValue(Streamer, Length, OffsetSize); Streamer.emitLabel(fdeStart); @@ -1755,12 +1745,12 @@ const MCAsmInfo *asmInfo = context.getAsmInfo(); if (IsEH) { const MCExpr *offset = - makeEndMinusStartExpr(context, cieStart, *fdeStart, 0); - emitAbsValue(Streamer, offset, OffsetSize); + MCDwarfHelper::makeEndMinusStartExpr(context, cieStart, *fdeStart, 0); + MCDwarfHelper::emitAbsValue(Streamer, offset, OffsetSize); } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) { - const MCExpr *offset = - makeEndMinusStartExpr(context, SectionStart, cieStart, 0); - emitAbsValue(Streamer, offset, OffsetSize); + const MCExpr *offset = MCDwarfHelper::makeEndMinusStartExpr( + context, SectionStart, cieStart, 0); + MCDwarfHelper::emitAbsValue(Streamer, offset, OffsetSize); } else { Streamer.emitSymbolValue(&cieStart, OffsetSize, asmInfo->needsDwarfSectionOffsetDirective()); @@ -1773,9 +1763,9 @@ emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH); // PC Range - const MCExpr *Range = - makeEndMinusStartExpr(context, *frame.Begin, *frame.End, 0); - emitAbsValue(Streamer, Range, PCSize); + const MCExpr *Range = MCDwarfHelper::makeEndMinusStartExpr( + context, *frame.Begin, *frame.End, 0); + MCDwarfHelper::emitAbsValue(Streamer, Range, PCSize); if (IsEH) { // Augmentation Data Length diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1014,6 +1014,27 @@ Hi, Lo, dwarf::getDwarfOffsetByteSize(Context.getDwarfFormat())); } +void MCStreamer::emitDwarfLineUnitLength(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned &Length) { + unsigned UnitLengthBytes = + dwarf::getUnitLengthFieldByteSize(Context.getDwarfFormat()); + unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Context.getDwarfFormat()); + + // Emit DWARF64 mark. + maybeEmitDwarf64Mark(); + + // Emit the length field. + // The 4 (8 for DWARF64) byte total length of the information for this + // compilation unit, not including the unit length field itself. + MCDwarfHelper::emitAbsValue( + *this, + MCDwarfHelper::makeEndMinusStartExpr(Context, *Hi, *Lo, UnitLengthBytes), + OffsetSize); + + // Set the length for the debug line length field. + Length = UnitLengthBytes; +} + void MCStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) { visitUsedExpr(*Value); Symbol->setVariableValue(Value);