diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -388,6 +388,14 @@ /// absolute difference. bool DwarfFDESymbolsUseAbsDiff = false; + /// True if the target supports generating the DWARF line table through using + /// the .loc/.file directives. Defaults to true. + bool UsesDwarfFileAndLocDirectives = true; + + /// True if the target needs the DWARF section length in the header (if any) + /// of the DWARF section in the assembly file. Defaults to true. + bool DwarfSectionSizeRequired = true; + /// True if dwarf register numbers are printed instead of symbolic register /// names in .cfi_* directives. Defaults to false. bool DwarfRegNumForCFI = false; @@ -673,6 +681,14 @@ return SupportsExtendedDwarfLocDirective; } + bool usesDwarfFileAndLocDirectives() const { + return UsesDwarfFileAndLocDirectives; + } + + bool needsDwarfSectionSizeInHeader() const { + return DwarfSectionSizeRequired; + } + void addInitialFrameState(const MCCFIInstruction &Inst); const std::vector &getInitialFrameState() const { diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -270,16 +270,35 @@ }; struct XCOFFSectionKey { + // Section name. std::string SectionName; - XCOFF::StorageMappingClass MappingClass; + // Section property. + // For csect section, it is storage mapping class. + // For debug section, it is section type flags. + union { + XCOFF::StorageMappingClass MappingClass; + XCOFF::DwarfSectionSubtypeFlags DwarfSubtypeFlags; + }; + bool IsCsect; XCOFFSectionKey(StringRef SectionName, XCOFF::StorageMappingClass MappingClass) - : SectionName(SectionName), MappingClass(MappingClass) {} + : SectionName(SectionName), MappingClass(MappingClass), + IsCsect(true) {} + + XCOFFSectionKey(StringRef SectionName, + XCOFF::DwarfSectionSubtypeFlags DwarfSubtypeFlags) + : SectionName(SectionName), DwarfSubtypeFlags(DwarfSubtypeFlags), + IsCsect(false) {} bool operator<(const XCOFFSectionKey &Other) const { - return std::tie(SectionName, MappingClass) < - std::tie(Other.SectionName, Other.MappingClass); + if (IsCsect && Other.IsCsect) + return std::tie(SectionName, MappingClass) < + std::tie(Other.SectionName, Other.MappingClass); + if (IsCsect != Other.IsCsect) + return IsCsect; + return std::tie(SectionName, DwarfSubtypeFlags) < + std::tie(Other.SectionName, Other.DwarfSubtypeFlags); } }; @@ -579,11 +598,11 @@ const MCSymbolWasm *Group, unsigned UniqueID, const char *BeginSymName); - MCSectionXCOFF * - getXCOFFSection(StringRef Section, SectionKind K, - Optional CsectProp = None, - bool MultiSymbolsAllowed = false, - const char *BeginSymName = nullptr); + MCSectionXCOFF *getXCOFFSection( + StringRef Section, SectionKind K, + Optional CsectProp = None, + bool MultiSymbolsAllowed = false, const char *BeginSymName = nullptr, + Optional DwarfSubtypeFlags = None); // Create and save a copy of STI and return a reference to the copy. MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI); 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 @@ -173,7 +173,7 @@ // This is called when an instruction is assembled into the specified // section and if there is information from the last .loc directive that // has yet to have a line entry made for it is made. - static void Make(MCObjectStreamer *MCOS, MCSection *Section); + static void make(MCStreamer *MCOS, MCSection *Section); }; /// Instances of this class represent the line information for a compile @@ -311,10 +311,10 @@ public: // This emits the Dwarf file and the line tables for all Compile Units. - static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params); + static void emit(MCStreamer *MCOS, MCDwarfLineTableParams Params); // This emits the Dwarf file and the line tables for a given Compile Unit. - void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params, + void emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, Optional &LineStr) const; Expected tryGetFile(StringRef &Directory, StringRef &FileName, diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -146,7 +146,8 @@ unsigned Discriminator, StringRef FileName) override; void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, - const MCSymbol *Label, unsigned PointerSize); + const MCSymbol *Label, + unsigned PointerSize) override; void emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label); void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, diff --git a/llvm/include/llvm/MC/MCSectionXCOFF.h b/llvm/include/llvm/MC/MCSectionXCOFF.h --- a/llvm/include/llvm/MC/MCSectionXCOFF.h +++ b/llvm/include/llvm/MC/MCSectionXCOFF.h @@ -35,6 +35,7 @@ Optional CsectProp; MCSymbolXCOFF *const QualName; StringRef SymbolTableName; + Optional DwarfSubtypeFlags; bool MultiSymbolsAllowed; static constexpr unsigned DefaultAlignVal = 4; @@ -44,12 +45,13 @@ bool MultiSymbolsAllowed) : MCSection(SV_XCOFF, Name, K, Begin), CsectProp(XCOFF::CsectProperties(SMC, ST)), QualName(QualName), - SymbolTableName(SymbolTableName), + SymbolTableName(SymbolTableName), DwarfSubtypeFlags(None), MultiSymbolsAllowed(MultiSymbolsAllowed) { assert( (ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM || ST == XCOFF::XTY_ER) && "Invalid or unhandled type for csect."); assert(QualName != nullptr && "QualName is needed."); + QualName->setRepresentedCsect(this); QualName->setStorageClass(XCOFF::C_HIDEXT); // A csect is 4 byte aligned by default, except for undefined symbol csects. @@ -58,10 +60,11 @@ } MCSectionXCOFF(StringRef Name, SectionKind K, MCSymbolXCOFF *QualName, + XCOFF::DwarfSectionSubtypeFlags DwarfSubtypeFlags, MCSymbol *Begin, StringRef SymbolTableName, bool MultiSymbolsAllowed) : MCSection(SV_XCOFF, Name, K, Begin), QualName(QualName), - SymbolTableName(SymbolTableName), + SymbolTableName(SymbolTableName), DwarfSubtypeFlags(DwarfSubtypeFlags), MultiSymbolsAllowed(MultiSymbolsAllowed) { assert(QualName != nullptr && "QualName is needed."); @@ -103,6 +106,10 @@ StringRef getSymbolTableName() const { return SymbolTableName; } bool isMultiSymbolsAllowed() const { return MultiSymbolsAllowed; } bool isCsect() const { return CsectProp.hasValue(); } + bool isDwarfSect() const { return DwarfSubtypeFlags.hasValue(); } + Optional getDwarfSubtypeFlags() const { + return DwarfSubtypeFlags; + } }; } // end namespace llvm 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 @@ -1092,6 +1092,20 @@ /// Return the end symbol generated inside, the caller needs to emit it. virtual MCSymbol *emitDwarfUnitLength(const Twine &Prefix, const Twine &Comment); + + /// Emit the debug line start label. + virtual void emitDwarfLineStartLabel(MCSymbol *StartSym); + + /// If targets does not support representing debug line section by .loc/.file + /// directives in assembly output, we need to populate debug line section with + /// raw debug line contents. + virtual void emitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize) {} + + /// Do finalization for the streamer at the end of a section. + virtual void doFinalizationAtSectionEnd(MCSection *Section) {} }; /// Create a dummy machine code streamer, which does nothing. This is useful for diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -392,11 +392,21 @@ DwarfVersion = TT.isNVPTX() ? 2 : (DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION); - bool Dwarf64 = - (Asm->TM.Options.MCOptions.Dwarf64 || MMI->getModule()->isDwarf64()) && - DwarfVersion >= 3 && // DWARF64 was introduced in DWARFv3. - TT.isArch64Bit() && // DWARF64 requires 64-bit relocations. - TT.isOSBinFormatELF(); // Support only ELF for now. + bool Dwarf64 = DwarfVersion >= 3 && // DWARF64 was introduced in DWARFv3. + TT.isArch64Bit(); // DWARF64 requires 64-bit relocations. + + // Support DWARF64 + // 1: For ELF when requested. + // 2: For XCOFF64: the AIX assembler will fill in debug section lengths + // according to the DWARF64 format for 64-bit assembly, so we must use + // DWARF64 in the compiler too for 64-bit mode. + Dwarf64 &= + ((Asm->TM.Options.MCOptions.Dwarf64 || MMI->getModule()->isDwarf64()) && + TT.isOSBinFormatELF()) || + TT.isOSBinFormatXCOFF(); + + if (!Dwarf64 && TT.isArch64Bit() && TT.isOSBinFormatXCOFF()) + report_fatal_error("XCOFF requires DWARF64 for 64-bit mode!"); UseRangesSection = !NoDwarfRangesSection && !TT.isNVPTX(); diff --git a/llvm/lib/MC/MCAsmInfoXCOFF.cpp b/llvm/lib/MC/MCAsmInfoXCOFF.cpp --- a/llvm/lib/MC/MCAsmInfoXCOFF.cpp +++ b/llvm/lib/MC/MCAsmInfoXCOFF.cpp @@ -23,6 +23,8 @@ PrivateLabelPrefix = "L.."; SupportsQuotedNames = false; UseDotAlignForAlignment = true; + UsesDwarfFileAndLocDirectives = false; + DwarfSectionSizeRequired = false; if (UseLEB128Directives == cl::BOU_UNSET) HasLEB128Directives = false; ZeroDirective = "\t.space\t"; diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -372,6 +372,19 @@ void emitRawTextImpl(StringRef String) override; void finishImpl() override; + + void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) override; + + MCSymbol *emitDwarfUnitLength(const Twine &Prefix, + const Twine &Comment) override; + + void emitDwarfLineStartLabel(MCSymbol *StartSym) override; + + void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize) override; + + void doFinalizationAtSectionEnd(MCSection *Section) override; }; } // end anonymous namespace. @@ -1419,7 +1432,11 @@ if (!FileNoOrErr) return FileNoOrErr.takeError(); FileNo = FileNoOrErr.get(); - if (NumFiles == Table.getMCDwarfFiles().size()) + + // Return early if this file is already emitted before or if target doesn't + // support .file directive. + if (NumFiles == Table.getMCDwarfFiles().size() || + !MAI->usesDwarfFileAndLocDirectives()) return FileNo; SmallString<128> Str; @@ -1448,6 +1465,10 @@ getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum, Source); + // Target doesn't support .loc/.file directives, return early. + if (!MAI->usesDwarfFileAndLocDirectives()) + return; + SmallString<128> Str; raw_svector_ostream OS1(Str); printDwarfFileDirective(0, Directory, Filename, Checksum, Source, @@ -1463,6 +1484,17 @@ unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator, StringRef FileName) { + // If target doesn't support .loc/.file directive, we need to record the lines + // same way like we do in object mode. + if (!MAI->usesDwarfFileAndLocDirectives()) { + // In case we see two .loc directives in a row, make sure the + // first one gets a line entry. + MCDwarfLineEntry::make(this, getCurrentSectionOnly()); + this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa, + Discriminator, FileName); + return; + } + OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; if (MAI->supportsExtendedDwarfLocDirective()) { if (Flags & DWARF2_FLAG_BASIC_BLOCK) @@ -2106,6 +2138,11 @@ assert(getCurrentSectionOnly() && "Cannot emit contents before setting section!"); + if (!MAI->usesDwarfFileAndLocDirectives()) + // Now that a machine instruction has been assembled into this section, make + // a line entry for any .loc directive that has been seen. + MCDwarfLineEntry::make(this, getCurrentSectionOnly()); + // Show the encoding in a comment if we have a code emitter. AddEncodingComment(Inst, STI); @@ -2197,6 +2234,13 @@ if (getContext().getGenDwarfForAssembly()) MCGenDwarfInfo::Emit(this); + // Now it is time to emit debug line sections if target doesn't support .loc + // and .line directives. + if (!MAI->usesDwarfFileAndLocDirectives()) { + MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams()); + return; + } + // Emit the label for the line table, if requested - since the rest of the // line table will be defined by .loc/.file directives, and not emitted // directly, the label is the only work required here. @@ -2210,6 +2254,118 @@ } } +void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) { + // If the assembler on some target fills in the DWARF unit length, we + // don't want to emit the length in the compiler. For example, the AIX + // assembler requires the assembly file with the unit length omitted from + // the debug section headers. In such cases, any label we placed occurs + // after the implied length field. We need to adjust the reference here + // to account for the offset introduced by the inserted length field. + if (!MAI->needsDwarfSectionSizeInHeader()) + return; + MCStreamer::emitDwarfUnitLength(Length, Comment); +} + +MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix, + const Twine &Comment) { + // If the assembler on some target fills in the DWARF unit length, we + // don't want to emit the length in the compiler. For example, the AIX + // assembler requires the assembly file with the unit length omitted from + // the debug section headers. In such cases, any label we placed occurs + // after the implied length field. We need to adjust the reference here + // to account for the offset introduced by the inserted length field. + if (!MAI->needsDwarfSectionSizeInHeader()) + return getContext().createTempSymbol(Prefix + "_end"); + return MCStreamer::emitDwarfUnitLength(Prefix, Comment); +} + +void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) { + // If the assembler on some target fills in the DWARF unit length, we + // don't want to emit the length in the compiler. For example, the AIX + // assembler requires the assembly file with the unit length omitted from + // the debug section headers. In such cases, any label we placed occurs + // after the implied length field. We need to adjust the reference here + // to account for the offset introduced by the inserted length field. + MCContext &Ctx = getContext(); + if (!MAI->needsDwarfSectionSizeInHeader()) { + MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_"); + // Emit the symbol which does not contain the unit length field. + emitLabel(DebugLineSymTmp); + + // Adjust the outer reference to account for the offset introduced by the + // inserted length field. + unsigned LengthFieldSize = + dwarf::getUnitLengthFieldByteSize(Ctx.getDwarfFormat()); + const MCExpr *EntrySize = MCConstantExpr::create(LengthFieldSize, Ctx); + const MCExpr *OuterSym = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(DebugLineSymTmp, Ctx), EntrySize, Ctx); + + emitAssignment(StartSym, OuterSym); + return; + } + MCStreamer::emitDwarfLineStartLabel(StartSym); +} + +// Generate DWARF line sections for assembly mode without .loc/.file +void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize) { + assert(!MAI->usesDwarfFileAndLocDirectives() && + ".loc/.file don't need raw data in debug line section!"); + if (!LastLabel) { + // Set to CU beginning. + emitIntValue(dwarf::DW_LNS_extended_op, 1); + emitULEB128IntValue(PointerSize + 1); + emitIntValue(dwarf::DW_LNE_set_address, 1); + emitSymbolValue(Label, PointerSize); + + // Emit the sequence for the LineDelta (from 1) and a zero address delta. + MCDwarfLineAddr::Emit(this, MCDwarfLineTableParams(), LineDelta, 0); + return; + } + + // INT64_MAX is a signal of the end of the section. Emit DW_LNE_end_sequence + // for the end of the section. + if (LineDelta == INT64_MAX) { + // Set new address to end label. + emitIntValue(dwarf::DW_LNS_extended_op, 1); + emitULEB128IntValue(PointerSize + 1); + emitIntValue(dwarf::DW_LNE_set_address, 1); + emitSymbolValue(Label, PointerSize); + + emitIntValue(0, 1); + emitULEB128IntValue(1); + emitIntValue(dwarf::DW_LNE_end_sequence, 1); + return; + } + + // Set new address to new label. + emitIntValue(dwarf::DW_LNS_extended_op, 1); + emitULEB128IntValue(PointerSize + 1); + emitIntValue(dwarf::DW_LNE_set_address, 1); + emitSymbolValue(Label, PointerSize); + + // Advance line. + emitIntValue(dwarf::DW_LNS_advance_line, 1); + emitSLEB128IntValue(LineDelta); + emitIntValue(dwarf::DW_LNS_copy, 1); +} + +void MCAsmStreamer::doFinalizationAtSectionEnd(MCSection *Section) { + // Emit section end. This is used to tell the debug line section where the end + // is for a text section if we don't use .loc to represent the debug line. + if (MAI->usesDwarfFileAndLocDirectives()) + return; + + SwitchSectionNoChange(Section); + + MCSymbol *Sym = getCurrentSectionOnly()->getEndSymbol(getContext()); + + if (!Sym->isInSection()) + emitLabel(Sym); +} + MCStreamer *llvm::createAsmStreamer(MCContext &Context, std::unique_ptr OS, bool isVerboseAsm, bool useDwarfDirectory, diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -671,15 +671,20 @@ return Result; } -MCSectionXCOFF * -MCContext::getXCOFFSection(StringRef Section, SectionKind Kind, - Optional CsectProp, - bool MultiSymbolsAllowed, const char *BeginSymName) { +MCSectionXCOFF *MCContext::getXCOFFSection( + StringRef Section, SectionKind Kind, + Optional CsectProp, bool MultiSymbolsAllowed, + const char *BeginSymName, + Optional DwarfSectionSubtypeFlags) { + bool IsDwarfSec = DwarfSectionSubtypeFlags.hasValue(); + assert((IsDwarfSec != CsectProp.hasValue()) && "Invalid XCOFF section!"); + // Do the lookup. If we have a hit, return it. - // FIXME: handle the case for non-csect sections. Non-csect section has None - // CsectProp. auto IterBool = XCOFFUniquingMap.insert(std::make_pair( - XCOFFSectionKey{Section.str(), CsectProp->MappingClass}, nullptr)); + IsDwarfSec + ? XCOFFSectionKey(Section.str(), DwarfSectionSubtypeFlags.getValue()) + : XCOFFSectionKey(Section.str(), CsectProp->MappingClass), + nullptr)); auto &Entry = *IterBool.first; if (!IterBool.second) { MCSectionXCOFF *ExistedEntry = Entry.second; @@ -691,9 +696,14 @@ // Otherwise, return a new section. StringRef CachedName = Entry.first.SectionName; - MCSymbolXCOFF *QualName = cast(getOrCreateSymbol( - CachedName + "[" + XCOFF::getMappingClassString(CsectProp->MappingClass) + - "]")); + MCSymbolXCOFF *QualName = nullptr; + // Debug section don't have storage class attribute. + if (IsDwarfSec) + QualName = cast(getOrCreateSymbol(CachedName)); + else + QualName = cast(getOrCreateSymbol( + CachedName + "[" + + XCOFF::getMappingClassString(CsectProp->MappingClass) + "]")); MCSymbol *Begin = nullptr; if (BeginSymName) @@ -701,9 +711,18 @@ // QualName->getUnqualifiedName() and CachedName are the same except when // CachedName contains invalid character(s) such as '$' for an XCOFF symbol. - MCSectionXCOFF *Result = new (XCOFFAllocator.Allocate()) MCSectionXCOFF( - QualName->getUnqualifiedName(), CsectProp->MappingClass, CsectProp->Type, - Kind, QualName, Begin, CachedName, MultiSymbolsAllowed); + MCSectionXCOFF *Result = nullptr; + if (IsDwarfSec) + Result = new (XCOFFAllocator.Allocate()) + MCSectionXCOFF(QualName->getUnqualifiedName(), Kind, QualName, + DwarfSectionSubtypeFlags.getValue(), Begin, CachedName, + MultiSymbolsAllowed); + else + Result = new (XCOFFAllocator.Allocate()) + MCSectionXCOFF(QualName->getUnqualifiedName(), CsectProp->MappingClass, + CsectProp->Type, Kind, QualName, Begin, CachedName, + MultiSymbolsAllowed); + Entry.second = Result; auto *F = new MCDataFragment(); 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 @@ -105,7 +105,7 @@ // and if there is information from the last .loc directive that has yet to have // a line entry made for it is made. // -void MCDwarfLineEntry::Make(MCObjectStreamer *MCOS, MCSection *Section) { +void MCDwarfLineEntry::make(MCStreamer *MCOS, MCSection *Section) { if (!MCOS->getContext().getDwarfLocSeen()) return; @@ -163,7 +163,7 @@ // in the LineSection. // static inline void emitDwarfLineTable( - MCObjectStreamer *MCOS, MCSection *Section, + MCStreamer *MCOS, MCSection *Section, const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { unsigned FileNum = 1; unsigned LastLine = 1; @@ -245,8 +245,7 @@ // // This emits the Dwarf file and the line tables. // -void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS, - MCDwarfLineTableParams Params) { +void MCDwarfLineTable::emit(MCStreamer *MCOS, MCDwarfLineTableParams Params) { MCContext &context = MCOS->getContext(); auto &LineTables = context.getMCDwarfLineTables(); @@ -266,7 +265,7 @@ // Handle the rest of the Compile Units. for (const auto &CUIDTablePair : LineTables) { - CUIDTablePair.second.EmitCU(MCOS, Params, LineStr); + CUIDTablePair.second.emitCU(MCOS, Params, LineStr); } if (LineStr) @@ -471,8 +470,9 @@ MCSymbol *LineStartSym = Label; if (!LineStartSym) LineStartSym = context.createTempSymbol(); + // Set the value of the symbol, as we are at the start of the line table. - MCOS->emitLabel(LineStartSym); + MCOS->emitDwarfLineStartLabel(LineStartSym); unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat()); @@ -529,8 +529,7 @@ return std::make_pair(LineStartSym, LineEndSym); } -void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS, - MCDwarfLineTableParams Params, +void MCDwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, Optional &LineStr) const { MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -909,18 +909,49 @@ // DWARF sections for XCOFF are not csects. They are special STYP_DWARF // sections, and the individual DWARF sections are distinguished by their // section subtype. - // TODO: Populate the DWARF sections appropriately. - DwarfAbbrevSection = nullptr; // SSUBTYP_DWABREV - DwarfInfoSection = nullptr; // SSUBTYP_DWINFO - DwarfLineSection = nullptr; // SSUBTYP_DWLINE - DwarfFrameSection = nullptr; // SSUBTYP_DWFRAME - DwarfPubNamesSection = nullptr; // SSUBTYP_DWPBNMS - DwarfPubTypesSection = nullptr; // SSUBTYP_DWPBTYP - DwarfStrSection = nullptr; // SSUBTYP_DWSTR - DwarfLocSection = nullptr; // SSUBTYP_DWLOC - DwarfARangesSection = nullptr; // SSUBTYP_DWARNGE - DwarfRangesSection = nullptr; // SSUBTYP_DWRNGES - DwarfMacinfoSection = nullptr; // SSUBTYP_DWMAC + DwarfAbbrevSection = Ctx->getXCOFFSection( + ".dwabrev", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwabrev", XCOFF::SSUBTYP_DWABREV); + + DwarfInfoSection = Ctx->getXCOFFSection( + ".dwinfo", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwinfo", XCOFF::SSUBTYP_DWINFO); + + DwarfLineSection = Ctx->getXCOFFSection( + ".dwline", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwline", XCOFF::SSUBTYP_DWLINE); + + DwarfFrameSection = Ctx->getXCOFFSection( + ".dwframe", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwframe", XCOFF::SSUBTYP_DWFRAME); + + DwarfPubNamesSection = Ctx->getXCOFFSection( + ".dwpbnms", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwpbnms", XCOFF::SSUBTYP_DWPBNMS); + + DwarfPubTypesSection = Ctx->getXCOFFSection( + ".dwpbtyp", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwpbtyp", XCOFF::SSUBTYP_DWPBTYP); + + DwarfStrSection = Ctx->getXCOFFSection( + ".dwstr", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwstr", XCOFF::SSUBTYP_DWSTR); + + DwarfLocSection = Ctx->getXCOFFSection( + ".dwloc", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwloc", XCOFF::SSUBTYP_DWLOC); + + DwarfARangesSection = Ctx->getXCOFFSection( + ".dwarnge", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwarnge", XCOFF::SSUBTYP_DWARNGE); + + DwarfRangesSection = Ctx->getXCOFFSection( + ".dwrnges", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwrnges", XCOFF::SSUBTYP_DWRNGES); + + DwarfMacinfoSection = Ctx->getXCOFFSection( + ".dwmac", SectionKind::getMetadata(), /* CsectProperties */ None, + /* MultiSymbolsAllowed */ true, ".dwmac", XCOFF::SSUBTYP_DWMAC); } void MCObjectFileInfo::InitMCObjectFileInfo(const Triple &TheTriple, bool PIC, diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -228,7 +228,7 @@ MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - MCDwarfLineEntry::Make(this, getCurrentSectionOnly()); + MCDwarfLineEntry::make(this, getCurrentSectionOnly()); // Avoid fixups when possible. int64_t AbsValue; @@ -385,7 +385,7 @@ // Now that a machine instruction has been assembled into this section, make // a line entry for any .loc directive that has been seen. - MCDwarfLineEntry::Make(this, getCurrentSectionOnly()); + MCDwarfLineEntry::make(this, getCurrentSectionOnly()); // If this instruction doesn't need relaxation, just emit it as data. MCAssembler &Assembler = getAssembler(); @@ -455,7 +455,7 @@ StringRef FileName) { // In case we see two .loc directives in a row, make sure the // first one gets a line entry. - MCDwarfLineEntry::Make(this, getCurrentSectionOnly()); + MCDwarfLineEntry::make(this, getCurrentSectionOnly()); this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa, Discriminator, FileName); @@ -573,7 +573,7 @@ } void MCObjectStreamer::emitBytes(StringRef Data) { - MCDwarfLineEntry::Make(this, getCurrentSectionOnly()); + MCDwarfLineEntry::make(this, getCurrentSectionOnly()); MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); DF->getContents().append(Data.begin(), Data.end()); @@ -850,7 +850,7 @@ MCGenDwarfInfo::Emit(this); // Dump out the dwarf file & directory tables and line tables. - MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams()); + MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams()); // Emit pseudo probes for the current module. MCPseudoProbeTable::emit(this); diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp --- a/llvm/lib/MC/MCSectionXCOFF.cpp +++ b/llvm/lib/MC/MCSectionXCOFF.cpp @@ -9,6 +9,8 @@ #include "llvm/MC/MCSectionXCOFF.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -70,6 +72,14 @@ return; } + // XCOFF debug sections. + if (getKind().isMetadata() && isDwarfSect()) { + OS << "\n\t.dwsect " + << format("0x%" PRIx32, getDwarfSubtypeFlags().getValue()) << '\n'; + OS << MAI.getPrivateLabelPrefix() << getName() << ':' << '\n'; + return; + } + report_fatal_error("Printing for this SectionKind is unimplemented."); } 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 @@ -1021,6 +1021,11 @@ return Hi; } +void MCStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) { + // Set the value of the symbol, as we are at the start of the line table. + emitLabel(StartSym); +} + void MCStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) { visitUsedExpr(*Value); Symbol->setVariableValue(Value); diff --git a/llvm/lib/MC/MCSymbolXCOFF.cpp b/llvm/lib/MC/MCSymbolXCOFF.cpp --- a/llvm/lib/MC/MCSymbolXCOFF.cpp +++ b/llvm/lib/MC/MCSymbolXCOFF.cpp @@ -13,9 +13,6 @@ MCSectionXCOFF *MCSymbolXCOFF::getRepresentedCsect() const { assert(RepresentedCsect && "Trying to get csect representation of this symbol but none was set."); - assert(!getName().equals(getUnqualifiedName()) && - "Symbol does not represent a csect; MCSectionXCOFF that represents " - "the symbol should not be (but is) set."); assert(getSymbolTableName().equals(RepresentedCsect->getSymbolTableName()) && "SymbolTableNames need to be the same for this symbol and its csect " "representation."); @@ -27,9 +24,6 @@ assert((!RepresentedCsect || RepresentedCsect == C) && "Trying to set a csect that doesn't match the one that this symbol is " "already mapped to."); - assert(!getName().equals(getUnqualifiedName()) && - "Symbol does not represent a csect; can only set a MCSectionXCOFF " - "representation for a csect."); assert(getSymbolTableName().equals(C->getSymbolTableName()) && "SymbolTableNames need to be the same for this symbol and its csect " "representation."); diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -63,4 +63,10 @@ // A size of 8 is only supported by the assembler under 64-bit. Data64bitsDirective = Is64Bit ? "\t.vbyte\t8, " : nullptr; + + // Debug Information + SupportsDebugInformation = true; + + // Set up DWARF directives + MinInstAlignment = 4; } diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1801,11 +1801,14 @@ } void PPCAIXAsmPrinter::emitFunctionBodyEnd() { - - if (!TM.getXCOFFTracebackTable()) - return; - - emitTracebackTable(); + // When -function-sections is enabled, generating function section end symbol + // to tell debug line section where is the end of current function section. + if (TM.getFunctionSections() && !MAI->usesDwarfFileAndLocDirectives() && + MMI->hasDebugInfo()) + OutStreamer->doFinalizationAtSectionEnd(MF->getSection()); + + if (TM.getXCOFFTracebackTable()) + emitTracebackTable(); } void PPCAIXAsmPrinter::emitTracebackTable() { @@ -2336,6 +2339,11 @@ } bool PPCAIXAsmPrinter::doFinalization(Module &M) { + // Do streamer related finalization for DWARF. + if (!MAI->usesDwarfFileAndLocDirectives() && MMI->hasDebugInfo()) + OutStreamer->doFinalizationAtSectionEnd( + OutStreamer->getContext().getObjectFileInfo()->getTextSection()); + for (MCSymbol *Sym : ExtSymSDNodeSymbols) OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern); return PPCAsmPrinter::doFinalization(M); diff --git a/llvm/test/DebugInfo/XCOFF/empty.ll b/llvm/test/DebugInfo/XCOFF/empty.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/XCOFF/empty.ll @@ -0,0 +1,436 @@ + +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | \ +; RUN: FileCheck %s --check-prefix=ASM32 +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | \ +; RUN: FileCheck %s --check-prefix=ASM64 + +source_filename = "1.c" +target datalayout = "E-m:a-p:32:32-i64:64-n32" + +; Function Attrs: noinline nounwind optnone +define i32 @main() #0 !dbg !8 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + ret i32 0, !dbg !12 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "1.c", directory: "debug") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 2} +!6 = !{i32 7, !"PIC Level", i32 2} +!7 = !{!"clang version 12.0.0"} +!8 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !9, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!9 = !DISubroutineType(types: !10) +!10 = !{!11} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !DILocation(line: 3, column: 3, scope: !8) + +; ASM32: .csect .text[PR],2 +; ASM32-NEXT: .file "1.c" +; ASM32-NEXT: .globl main[DS] # -- Begin function main +; ASM32-NEXT: .globl .main +; ASM32-NEXT: .align 2 +; ASM32-NEXT: .csect main[DS],2 +; ASM32-NEXT: .vbyte 4, .main # @main +; ASM32-NEXT: .vbyte 4, TOC[TC0] +; ASM32-NEXT: .vbyte 4, 0 +; ASM32-NEXT: .csect .text[PR],2 +; ASM32-NEXT: .main: +; ASM32-NEXT: L..func_begin0: +; ASM32-NEXT: # %bb.0: # %entry +; ASM32-NEXT: L..tmp0: +; ASM32-NEXT: li 4, 0 +; ASM32-NEXT: L..tmp1: +; ASM32-NEXT: L..tmp2: +; ASM32-NEXT: li 3, 0 +; ASM32-NEXT: stw 4, -4(1) +; ASM32-NEXT: blr +; ASM32-NEXT: L..tmp3: +; ASM32-NEXT: L..main0: +; ASM32-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; ASM32-NEXT: .byte 0x00 # Version = 0 +; ASM32-NEXT: .byte 0x09 # Language = CPlusPlus +; ASM32-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; ASM32-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; ASM32-NEXT: # -HasControlledStorage, -IsTOCless +; ASM32-NEXT: # -IsFloatingPointPresent +; ASM32-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; ASM32-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; ASM32-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +; ASM32-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; ASM32-NEXT: .byte 0x00 # -HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; ASM32-NEXT: .byte 0x00 # NumberOfFixedParms = 0 +; ASM32-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; ASM32-NEXT: .vbyte 4, L..main0-.main # Function size +; ASM32-NEXT: .vbyte 2, 0x0004 # Function name len = 4 +; ASM32-NEXT: .byte 'm,'a,'i,'n # Function Name +; ASM32-NEXT: L..func_end0: +; ASM32-NEXT: # -- End function +; ASM32-NEXT: L..sec_end0: +; ASM32: .dwsect 0x60000 +; ASM32-NEXT: L...dwabrev: +; ASM32-NEXT: .byte 1 # Abbreviation Code +; ASM32-NEXT: .byte 17 # DW_TAG_compile_unit +; ASM32-NEXT: .byte 1 # DW_CHILDREN_yes +; ASM32-NEXT: .byte 37 # DW_AT_producer +; ASM32-NEXT: .byte 14 # DW_FORM_strp +; ASM32-NEXT: .byte 19 # DW_AT_language +; ASM32-NEXT: .byte 5 # DW_FORM_data2 +; ASM32-NEXT: .byte 3 # DW_AT_name +; ASM32-NEXT: .byte 14 # DW_FORM_strp +; ASM32-NEXT: .byte 16 # DW_AT_stmt_list +; ASM32-NEXT: .byte 23 # DW_FORM_sec_offset +; ASM32-NEXT: .byte 27 # DW_AT_comp_dir +; ASM32-NEXT: .byte 14 # DW_FORM_strp +; ASM32-NEXT: .byte 17 # DW_AT_low_pc +; ASM32-NEXT: .byte 1 # DW_FORM_addr +; ASM32-NEXT: .byte 18 # DW_AT_high_pc +; ASM32-NEXT: .byte 6 # DW_FORM_data4 +; ASM32-NEXT: .byte 0 # EOM(1) +; ASM32-NEXT: .byte 0 # EOM(2) +; ASM32-NEXT: .byte 2 # Abbreviation Code +; ASM32-NEXT: .byte 46 # DW_TAG_subprogram +; ASM32-NEXT: .byte 0 # DW_CHILDREN_no +; ASM32-NEXT: .byte 17 # DW_AT_low_pc +; ASM32-NEXT: .byte 1 # DW_FORM_addr +; ASM32-NEXT: .byte 18 # DW_AT_high_pc +; ASM32-NEXT: .byte 6 # DW_FORM_data4 +; ASM32-NEXT: .byte 64 # DW_AT_frame_base +; ASM32-NEXT: .byte 24 # DW_FORM_exprloc +; ASM32-NEXT: .byte 3 # DW_AT_name +; ASM32-NEXT: .byte 14 # DW_FORM_strp +; ASM32-NEXT: .byte 58 # DW_AT_decl_file +; ASM32-NEXT: .byte 11 # DW_FORM_data1 +; ASM32-NEXT: .byte 59 # DW_AT_decl_line +; ASM32-NEXT: .byte 11 # DW_FORM_data1 +; ASM32-NEXT: .byte 39 # DW_AT_prototyped +; ASM32-NEXT: .byte 25 # DW_FORM_flag_present +; ASM32-NEXT: .byte 73 # DW_AT_type +; ASM32-NEXT: .byte 19 # DW_FORM_ref4 +; ASM32-NEXT: .byte 63 # DW_AT_external +; ASM32-NEXT: .byte 25 # DW_FORM_flag_present +; ASM32-NEXT: .byte 0 # EOM(1) +; ASM32-NEXT: .byte 0 # EOM(2) +; ASM32-NEXT: .byte 3 # Abbreviation Code +; ASM32-NEXT: .byte 36 # DW_TAG_base_type +; ASM32-NEXT: .byte 0 # DW_CHILDREN_no +; ASM32-NEXT: .byte 3 # DW_AT_name +; ASM32-NEXT: .byte 14 # DW_FORM_strp +; ASM32-NEXT: .byte 62 # DW_AT_encoding +; ASM32-NEXT: .byte 11 # DW_FORM_data1 +; ASM32-NEXT: .byte 11 # DW_AT_byte_size +; ASM32-NEXT: .byte 11 # DW_FORM_data1 +; ASM32-NEXT: .byte 0 # EOM(1) +; ASM32-NEXT: .byte 0 # EOM(2) +; ASM32-NEXT: .byte 0 # EOM(3) +; ASM32: .dwsect 0x10000 +; ASM32-NEXT: L...dwinfo: +; ASM32-NEXT: L..cu_begin0: +; ASM32-NEXT: .vbyte 2, 4 # DWARF version number +; ASM32-NEXT: .vbyte 4, L...dwabrev # Offset Into Abbrev. Section +; ASM32-NEXT: .byte 4 # Address Size (in bytes) +; ASM32-NEXT: .byte 1 # Abbrev [1] 0xb:0x38 DW_TAG_compile_unit +; ASM32-NEXT: .vbyte 4, L..info_string0 # DW_AT_producer +; ASM32-NEXT: .vbyte 2, 12 # DW_AT_language +; ASM32-NEXT: .vbyte 4, L..info_string1 # DW_AT_name +; ASM32-NEXT: .vbyte 4, L..line_table_start0 # DW_AT_stmt_list +; ASM32-NEXT: .vbyte 4, L..info_string2 # DW_AT_comp_dir +; ASM32-NEXT: .vbyte 4, L..func_begin0 # DW_AT_low_pc +; ASM32-NEXT: .vbyte 4, L..func_end0-L..func_begin0 # DW_AT_high_pc +; ASM32-NEXT: .byte 2 # Abbrev [2] 0x26:0x15 DW_TAG_subprogram +; ASM32-NEXT: .vbyte 4, L..func_begin0 # DW_AT_low_pc +; ASM32-NEXT: .vbyte 4, L..func_end0-L..func_begin0 # DW_AT_high_pc +; ASM32-NEXT: .byte 1 # DW_AT_frame_base +; ASM32-NEXT: .byte 81 +; ASM32-NEXT: .vbyte 4, L..info_string3 # DW_AT_name +; ASM32-NEXT: .byte 1 # DW_AT_decl_file +; ASM32-NEXT: .byte 1 # DW_AT_decl_line +; ASM32-NEXT: # DW_AT_prototyped +; ASM32-NEXT: .vbyte 4, 59 # DW_AT_type +; ASM32-NEXT: # DW_AT_external +; ASM32-NEXT: .byte 3 # Abbrev [3] 0x3b:0x7 DW_TAG_base_type +; ASM32-NEXT: .vbyte 4, L..info_string4 # DW_AT_name +; ASM32-NEXT: .byte 5 # DW_AT_encoding +; ASM32-NEXT: .byte 4 # DW_AT_byte_size +; ASM32-NEXT: .byte 0 # End Of Children Mark +; ASM32-NEXT: L..debug_info_end0: +; ASM32: .dwsect 0x70000 +; ASM32-NEXT: L...dwstr: +; ASM32-NEXT: L..info_string0: +; ASM32-NEXT: .byte 'c,'l,'a,'n,'g,' ,'v,'e,'r,'s,'i,'o,'n,' ,'1,'2,'.,'0,'.,'0,0000 # string offset=0 +; ASM32-NEXT: L..info_string1: +; ASM32-NEXT: .byte '1,'.,'c,0000 # string offset=21 +; ASM32-NEXT: L..info_string2: +; ASM32-NEXT: .byte 'd,'e,'b,'u,'g,0000 # string offset=25 +; ASM32-NEXT: L..info_string3: +; ASM32-NEXT: .byte 'm,'a,'i,'n,0000 # string offset=31 +; ASM32-NEXT: L..info_string4: +; ASM32-NEXT: .byte 'i,'n,'t,0000 # string offset=36 +; ASM32-NEXT: .toc +; ASM32: .dwsect 0x20000 +; ASM32-NEXT: L...dwline: +; ASM32-NEXT: L..debug_line_0: +; ASM32-NEXT: .set L..line_table_start0, L..debug_line_0-4 +; ASM32-NEXT: .vbyte 2, 4 +; ASM32-NEXT: .vbyte 4, L..tmp5-L..tmp4 +; ASM32-NEXT: L..tmp4: +; ASM32-NEXT: .byte 4 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte -5 +; ASM32-NEXT: .byte 14 +; ASM32-NEXT: .byte 13 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 'd,'e,'b,'u,'g +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte '1,'.,'c +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: L..tmp5: +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 5 +; ASM32-NEXT: .byte 2 +; ASM32-NEXT: .vbyte 4, L..tmp0 +; ASM32-NEXT: .byte 19 +; ASM32-NEXT: .byte 5 +; ASM32-NEXT: .byte 3 +; ASM32-NEXT: .byte 10 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 5 +; ASM32-NEXT: .byte 2 +; ASM32-NEXT: .vbyte 4, L..tmp2 +; ASM32-NEXT: .byte 3 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 5 +; ASM32-NEXT: .byte 2 +; ASM32-NEXT: .vbyte 4, L..sec_end0 +; ASM32-NEXT: .byte 0 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: L..debug_line_end0: + +; ASM64: .csect .text[PR],2 +; ASM64-NEXT: .file "1.c" +; ASM64-NEXT: .globl main[DS] # -- Begin function main +; ASM64-NEXT: .globl .main +; ASM64-NEXT: .align 2 +; ASM64-NEXT: .csect main[DS],3 +; ASM64-NEXT: .vbyte 8, .main # @main +; ASM64-NEXT: .vbyte 8, TOC[TC0] +; ASM64-NEXT: .vbyte 8, 0 +; ASM64-NEXT: .csect .text[PR],2 +; ASM64-NEXT: .main: +; ASM64-NEXT: L..func_begin0: +; ASM64-NEXT: # %bb.0: # %entry +; ASM64-NEXT: L..tmp0: +; ASM64-NEXT: li 4, 0 +; ASM64-NEXT: L..tmp1: +; ASM64-NEXT: L..tmp2: +; ASM64-NEXT: li 3, 0 +; ASM64-NEXT: stw 4, -4(1) +; ASM64-NEXT: blr +; ASM64-NEXT: L..tmp3: +; ASM64-NEXT: L..main0: +; ASM64-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; ASM64-NEXT: .byte 0x00 # Version = 0 +; ASM64-NEXT: .byte 0x09 # Language = CPlusPlus +; ASM64-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; ASM64-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; ASM64-NEXT: # -HasControlledStorage, -IsTOCless +; ASM64-NEXT: # -IsFloatingPointPresent +; ASM64-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; ASM64-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; ASM64-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +; ASM64-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; ASM64-NEXT: .byte 0x00 # -HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; ASM64-NEXT: .byte 0x00 # NumberOfFixedParms = 0 +; ASM64-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; ASM64-NEXT: .vbyte 4, L..main0-.main # Function size +; ASM64-NEXT: .vbyte 2, 0x0004 # Function name len = 4 +; ASM64-NEXT: .byte 'm,'a,'i,'n # Function Name +; ASM64-NEXT: L..func_end0: +; ASM64-NEXT: # -- End function +; ASM64-NEXT: L..sec_end0: +; ASM64: .dwsect 0x60000 +; ASM64-NEXT: L...dwabrev: +; ASM64-NEXT: .byte 1 # Abbreviation Code +; ASM64-NEXT: .byte 17 # DW_TAG_compile_unit +; ASM64-NEXT: .byte 1 # DW_CHILDREN_yes +; ASM64-NEXT: .byte 37 # DW_AT_producer +; ASM64-NEXT: .byte 14 # DW_FORM_strp +; ASM64-NEXT: .byte 19 # DW_AT_language +; ASM64-NEXT: .byte 5 # DW_FORM_data2 +; ASM64-NEXT: .byte 3 # DW_AT_name +; ASM64-NEXT: .byte 14 # DW_FORM_strp +; ASM64-NEXT: .byte 16 # DW_AT_stmt_list +; ASM64-NEXT: .byte 23 # DW_FORM_sec_offset +; ASM64-NEXT: .byte 27 # DW_AT_comp_dir +; ASM64-NEXT: .byte 14 # DW_FORM_strp +; ASM64-NEXT: .byte 17 # DW_AT_low_pc +; ASM64-NEXT: .byte 1 # DW_FORM_addr +; ASM64-NEXT: .byte 18 # DW_AT_high_pc +; ASM64-NEXT: .byte 6 # DW_FORM_data4 +; ASM64-NEXT: .byte 0 # EOM(1) +; ASM64-NEXT: .byte 0 # EOM(2) +; ASM64-NEXT: .byte 2 # Abbreviation Code +; ASM64-NEXT: .byte 46 # DW_TAG_subprogram +; ASM64-NEXT: .byte 0 # DW_CHILDREN_no +; ASM64-NEXT: .byte 17 # DW_AT_low_pc +; ASM64-NEXT: .byte 1 # DW_FORM_addr +; ASM64-NEXT: .byte 18 # DW_AT_high_pc +; ASM64-NEXT: .byte 6 # DW_FORM_data4 +; ASM64-NEXT: .byte 64 # DW_AT_frame_base +; ASM64-NEXT: .byte 24 # DW_FORM_exprloc +; ASM64-NEXT: .byte 3 # DW_AT_name +; ASM64-NEXT: .byte 14 # DW_FORM_strp +; ASM64-NEXT: .byte 58 # DW_AT_decl_file +; ASM64-NEXT: .byte 11 # DW_FORM_data1 +; ASM64-NEXT: .byte 59 # DW_AT_decl_line +; ASM64-NEXT: .byte 11 # DW_FORM_data1 +; ASM64-NEXT: .byte 39 # DW_AT_prototyped +; ASM64-NEXT: .byte 25 # DW_FORM_flag_present +; ASM64-NEXT: .byte 73 # DW_AT_type +; ASM64-NEXT: .byte 19 # DW_FORM_ref4 +; ASM64-NEXT: .byte 63 # DW_AT_external +; ASM64-NEXT: .byte 25 # DW_FORM_flag_present +; ASM64-NEXT: .byte 0 # EOM(1) +; ASM64-NEXT: .byte 0 # EOM(2) +; ASM64-NEXT: .byte 3 # Abbreviation Code +; ASM64-NEXT: .byte 36 # DW_TAG_base_type +; ASM64-NEXT: .byte 0 # DW_CHILDREN_no +; ASM64-NEXT: .byte 3 # DW_AT_name +; ASM64-NEXT: .byte 14 # DW_FORM_strp +; ASM64-NEXT: .byte 62 # DW_AT_encoding +; ASM64-NEXT: .byte 11 # DW_FORM_data1 +; ASM64-NEXT: .byte 11 # DW_AT_byte_size +; ASM64-NEXT: .byte 11 # DW_FORM_data1 +; ASM64-NEXT: .byte 0 # EOM(1) +; ASM64-NEXT: .byte 0 # EOM(2) +; ASM64-NEXT: .byte 0 # EOM(3) +; ASM64: .dwsect 0x10000 +; ASM64-NEXT: L...dwinfo: +; ASM64-NEXT: L..cu_begin0: +; ASM64-NEXT: .vbyte 2, 4 # DWARF version number +; ASM64-NEXT: .vbyte 8, L...dwabrev # Offset Into Abbrev. Section +; ASM64-NEXT: .byte 8 # Address Size (in bytes) +; ASM64-NEXT: .byte 1 # Abbrev [1] 0x17:0x58 DW_TAG_compile_unit +; ASM64-NEXT: .vbyte 8, L..info_string0 # DW_AT_producer +; ASM64-NEXT: .vbyte 2, 12 # DW_AT_language +; ASM64-NEXT: .vbyte 8, L..info_string1 # DW_AT_name +; ASM64-NEXT: .vbyte 8, L..line_table_start0 # DW_AT_stmt_list +; ASM64-NEXT: .vbyte 8, L..info_string2 # DW_AT_comp_dir +; ASM64-NEXT: .vbyte 8, L..func_begin0 # DW_AT_low_pc +; ASM64-NEXT: .vbyte 4, L..func_end0-L..func_begin0 # DW_AT_high_pc +; ASM64-NEXT: .byte 2 # Abbrev [2] 0x46:0x1d DW_TAG_subprogram +; ASM64-NEXT: .vbyte 8, L..func_begin0 # DW_AT_low_pc +; ASM64-NEXT: .vbyte 4, L..func_end0-L..func_begin0 # DW_AT_high_pc +; ASM64-NEXT: .byte 1 # DW_AT_frame_base +; ASM64-NEXT: .byte 81 +; ASM64-NEXT: .vbyte 8, L..info_string3 # DW_AT_name +; ASM64-NEXT: .byte 1 # DW_AT_decl_file +; ASM64-NEXT: .byte 1 # DW_AT_decl_line +; ASM64-NEXT: # DW_AT_prototyped +; ASM64-NEXT: .vbyte 4, 99 # DW_AT_type +; ASM64-NEXT: # DW_AT_external +; ASM64-NEXT: .byte 3 # Abbrev [3] 0x63:0xb DW_TAG_base_type +; ASM64-NEXT: .vbyte 8, L..info_string4 # DW_AT_name +; ASM64-NEXT: .byte 5 # DW_AT_encoding +; ASM64-NEXT: .byte 4 # DW_AT_byte_size +; ASM64-NEXT: .byte 0 # End Of Children Mark +; ASM64-NEXT: L..debug_info_end0: +; ASM64: .dwsect 0x70000 +; ASM64-NEXT: L...dwstr: +; ASM64-NEXT: L..info_string0: +; ASM64-NEXT: .byte 'c,'l,'a,'n,'g,' ,'v,'e,'r,'s,'i,'o,'n,' ,'1,'2,'.,'0,'.,'0,0000 # string offset=0 +; ASM64-NEXT: L..info_string1: +; ASM64-NEXT: .byte '1,'.,'c,0000 # string offset=21 +; ASM64-NEXT: L..info_string2: +; ASM64-NEXT: .byte 'd,'e,'b,'u,'g,0000 # string offset=25 +; ASM64-NEXT: L..info_string3: +; ASM64-NEXT: .byte 'm,'a,'i,'n,0000 # string offset=31 +; ASM64-NEXT: L..info_string4: +; ASM64-NEXT: .byte 'i,'n,'t,0000 # string offset=36 +; ASM64-NEXT: .toc +; ASM64: .dwsect 0x20000 +; ASM64-NEXT: L...dwline: +; ASM64-NEXT: L..debug_line_0: +; ASM64-NEXT: .set L..line_table_start0, L..debug_line_0-12 +; ASM64-NEXT: .vbyte 2, 4 +; ASM64-NEXT: .vbyte 8, L..tmp5-L..tmp4 +; ASM64-NEXT: L..tmp4: +; ASM64-NEXT: .byte 4 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte -5 +; ASM64-NEXT: .byte 14 +; ASM64-NEXT: .byte 13 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 'd,'e,'b,'u,'g +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte '1,'.,'c +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: L..tmp5: +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 9 +; ASM64-NEXT: .byte 2 +; ASM64-NEXT: .vbyte 8, L..tmp0 +; ASM64-NEXT: .byte 19 +; ASM64-NEXT: .byte 5 +; ASM64-NEXT: .byte 3 +; ASM64-NEXT: .byte 10 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 9 +; ASM64-NEXT: .byte 2 +; ASM64-NEXT: .vbyte 8, L..tmp2 +; ASM64-NEXT: .byte 3 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 9 +; ASM64-NEXT: .byte 2 +; ASM64-NEXT: .vbyte 8, L..sec_end0 +; ASM64-NEXT: .byte 0 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: L..debug_line_end0: diff --git a/llvm/test/DebugInfo/XCOFF/lit.local.cfg b/llvm/test/DebugInfo/XCOFF/lit.local.cfg new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/XCOFF/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'PowerPC' in config.root.targets: + config.unsupported = True