diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 9b2ac558756..309932b29bb 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -388,6 +388,14 @@ protected: /// 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 @@ public: 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/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 33874e83ead..106763c5d7c 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -279,16 +279,35 @@ namespace llvm { }; 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); } }; @@ -599,11 +618,11 @@ namespace llvm { 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/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 5bf6496806d..625e83a37da 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -173,7 +173,7 @@ public: // 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 @@ class MCDwarfLineTable { 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/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index a00000bc11b..a0169c4c822 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -146,7 +146,9 @@ public: 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 emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override; void emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label); void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, diff --git a/include/llvm/MC/MCSectionXCOFF.h b/include/llvm/MC/MCSectionXCOFF.h index 768e398525b..27c06a2c087 100644 --- a/include/llvm/MC/MCSectionXCOFF.h +++ b/include/llvm/MC/MCSectionXCOFF.h @@ -35,6 +35,7 @@ class MCSectionXCOFF final : public MCSection { Optional CsectProp; MCSymbolXCOFF *const QualName; StringRef SymbolTableName; + Optional DwarfSubtypeFlags; bool MultiSymbolsAllowed; static constexpr unsigned DefaultAlignVal = 4; @@ -44,12 +45,13 @@ class MCSectionXCOFF final : public MCSection { 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 @@ class MCSectionXCOFF final : public MCSection { } 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 @@ public: 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/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 7f50995fbda..4156d69c4c0 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -1092,6 +1092,23 @@ public: /// 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); + + /// Emit the debug line end entry. + virtual void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) {} + + /// 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/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 438492e9f19..beed2a5126c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -392,11 +392,21 @@ DwarfDebug::DwarfDebug(AsmPrinter *A) 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/lib/MC/MCAsmInfoXCOFF.cpp b/lib/MC/MCAsmInfoXCOFF.cpp index 2f8bc6a49bb..a23a71b865b 100644 --- a/lib/MC/MCAsmInfoXCOFF.cpp +++ b/lib/MC/MCAsmInfoXCOFF.cpp @@ -23,6 +23,8 @@ MCAsmInfoXCOFF::MCAsmInfoXCOFF() { PrivateLabelPrefix = "L.."; SupportsQuotedNames = false; UseDotAlignForAlignment = true; + UsesDwarfFileAndLocDirectives = false; + DwarfSectionSizeRequired = false; if (UseLEB128Directives == cl::BOU_UNSET) HasLEB128Directives = false; ZeroDirective = "\t.space\t"; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 10d72553fe6..e82ad28da64 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -372,6 +372,21 @@ public: 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 emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) 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 +1434,11 @@ Expected MCAsmStreamer::tryEmitDwarfFileDirective( 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 +1467,10 @@ void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory, 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 +1486,17 @@ void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, 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 +2140,11 @@ void MCAsmStreamer::emitInstruction(const MCInst &Inst, 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 +2236,13 @@ void MCAsmStreamer::finishImpl() { 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 +2256,135 @@ void MCAsmStreamer::finishImpl() { } } +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); +} + +void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section, + MCSymbol *LastLabel) { + // If the targets write the raw debug line data for assembly output (We can + // not switch to Section and add the end symbol there for assembly output) + // we currently use the .text end label as any section end. This will not + // impact the debugability as we will jump to the caller of the last function + // in the section before we come into the .text end address. + assert(!MAI->usesDwarfFileAndLocDirectives() && + ".loc should not be generated together with raw data!"); + + MCContext &Ctx = getContext(); + + // FIXME: use section end symbol as end of the Section. We need to consider + // the explicit sections and -ffunction-sections when we try to generate or + // find section end symbol for the Section. + MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection(); + assert(TextSection->hasEnded() && ".text section is not end!"); + + MCSymbol *SectionEnd = TextSection->getEndSymbol(Ctx); + const MCAsmInfo *AsmInfo = Ctx.getAsmInfo(); + emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, + AsmInfo->getCodePointerSize()); +} + +// 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!"); + + // Set to new address. + AddComment("Set address to " + Label->getName()); + emitIntValue(dwarf::DW_LNS_extended_op, 1); + emitULEB128IntValue(PointerSize + 1); + emitIntValue(dwarf::DW_LNE_set_address, 1); + emitSymbolValue(Label, PointerSize); + + if (!LastLabel) { + // Emit the sequence for the LineDelta (from 1) and a zero address delta. + AddComment("Start sequence"); + 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) { + AddComment("End sequence"); + emitIntValue(dwarf::DW_LNS_extended_op, 1); + emitULEB128IntValue(1); + emitIntValue(dwarf::DW_LNE_end_sequence, 1); + return; + } + + // Advance line. + AddComment("Advance line " + Twine(LineDelta)); + 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/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index b0eb47069d7..cf7e38f0949 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -686,15 +686,20 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind, 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; @@ -706,9 +711,14 @@ MCContext::getXCOFFSection(StringRef Section, SectionKind Kind, // 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) @@ -716,9 +726,18 @@ MCContext::getXCOFFSection(StringRef Section, SectionKind Kind, // 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/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index df04f113741..6c23d330e0e 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -105,7 +105,7 @@ static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) { // 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 @@ makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) { // 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; @@ -226,27 +226,14 @@ static inline void emitDwarfLineTable( LastLabel = Label; } - // Emit a DW_LNE_end_sequence for the end of the section. - // Use the section end label to compute the address delta and use INT64_MAX - // as the line delta which is the signal that this is actually a - // DW_LNE_end_sequence. - MCSymbol *SectionEnd = MCOS->endSection(Section); - - // Switch back the dwarf line section, in case endSection had to switch the - // section. - MCContext &Ctx = MCOS->getContext(); - MCOS->SwitchSection(Ctx.getObjectFileInfo()->getDwarfLineSection()); - - const MCAsmInfo *AsmInfo = Ctx.getAsmInfo(); - MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, - AsmInfo->getCodePointerSize()); + // Generate DWARF line end entry. + MCOS->emitDwarfLineEndEntry(Section, LastLabel); } // // 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 +253,7 @@ void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS, // 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 +458,9 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 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 +517,7 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 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/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index 06c1ae6b071..155104cddda 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -914,18 +914,49 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) { // 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/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 1c23d31f874..299f2a719fb 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -9,12 +9,14 @@ #include "llvm/MC/MCObjectStreamer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCCodeView.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" @@ -228,7 +230,7 @@ void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, 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 +387,7 @@ void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst, // 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 +457,7 @@ void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, 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); @@ -505,6 +507,24 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta)); } +void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section, + MCSymbol *LastLabel) { + // Emit a DW_LNE_end_sequence for the end of the section. + // Use the section end label to compute the address delta and use INT64_MAX + // as the line delta which is the signal that this is actually a + // DW_LNE_end_sequence. + MCSymbol *SectionEnd = endSection(Section); + + // Switch back the dwarf line section, in case endSection had to switch the + // section. + MCContext &Ctx = getContext(); + SwitchSection(Ctx.getObjectFileInfo()->getDwarfLineSection()); + + const MCAsmInfo *AsmInfo = Ctx.getAsmInfo(); + emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, + AsmInfo->getCodePointerSize()); +} + void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label) { const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel); @@ -573,7 +593,7 @@ void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) { } 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 +870,7 @@ void MCObjectStreamer::finishImpl() { 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/lib/MC/MCSectionXCOFF.cpp b/lib/MC/MCSectionXCOFF.cpp index 8c01f7f0dc4..2adddd31697 100644 --- a/lib/MC/MCSectionXCOFF.cpp +++ b/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; @@ -68,7 +70,7 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, // Common csect type (uninitialized storage) does not have to print csect // directive for section switching. - if (getCSectType() == XCOFF::XTY_CM) { + if (isCsect() && getCSectType() == XCOFF::XTY_CM) { assert((getMappingClass() == XCOFF::XMC_RW || getMappingClass() == XCOFF::XMC_BS || getMappingClass() == XCOFF::XMC_UL) && @@ -95,6 +97,14 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, 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/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index b2fc54236f7..afaa5700510 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -1019,6 +1019,11 @@ MCSymbol *MCStreamer::emitDwarfUnitLength(const Twine &Prefix, 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/lib/MC/MCSymbolXCOFF.cpp b/lib/MC/MCSymbolXCOFF.cpp index b9dd2908b40..b4c96a1ffa2 100644 --- a/lib/MC/MCSymbolXCOFF.cpp +++ b/lib/MC/MCSymbolXCOFF.cpp @@ -13,9 +13,6 @@ using namespace llvm; 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 @@ void MCSymbolXCOFF::setRepresentedCsect(MCSectionXCOFF *C) { 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/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp index 2b76af279ce..b0f52679d3d 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -63,4 +63,10 @@ PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) { // 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/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index ddfca2a764d..4e307dfc1e8 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -2303,6 +2303,11 @@ void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) { } 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/test/DebugInfo/XCOFF/empty.ll b/test/DebugInfo/XCOFF/empty.ll new file mode 100644 index 00000000000..1e65797f480 --- /dev/null +++ b/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 # Set address to L..tmp0 +; ASM32-NEXT: .byte 5 +; ASM32-NEXT: .byte 2 +; ASM32-NEXT: .vbyte 4, L..tmp0 +; ASM32-NEXT: .byte 19 # Start sequence +; ASM32-NEXT: .byte 5 +; ASM32-NEXT: .byte 3 +; ASM32-NEXT: .byte 10 +; ASM32-NEXT: .byte 0 # Set address to L..tmp2 +; ASM32-NEXT: .byte 5 +; ASM32-NEXT: .byte 2 +; ASM32-NEXT: .vbyte 4, L..tmp2 +; ASM32-NEXT: .byte 3 # Advance line 1 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 1 +; ASM32-NEXT: .byte 0 # Set address to L..sec_end0 +; ASM32-NEXT: .byte 5 +; ASM32-NEXT: .byte 2 +; ASM32-NEXT: .vbyte 4, L..sec_end0 +; ASM32-NEXT: .byte 0 # End sequence +; 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 # Set address to L..tmp0 +; ASM64-NEXT: .byte 9 +; ASM64-NEXT: .byte 2 +; ASM64-NEXT: .vbyte 8, L..tmp0 +; ASM64-NEXT: .byte 19 # Start sequence +; ASM64-NEXT: .byte 5 +; ASM64-NEXT: .byte 3 +; ASM64-NEXT: .byte 10 +; ASM64-NEXT: .byte 0 # Set address to L..tmp2 +; ASM64-NEXT: .byte 9 +; ASM64-NEXT: .byte 2 +; ASM64-NEXT: .vbyte 8, L..tmp2 +; ASM64-NEXT: .byte 3 # Advance line 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 0 # Set address to L..sec_end0 +; ASM64-NEXT: .byte 9 +; ASM64-NEXT: .byte 2 +; ASM64-NEXT: .vbyte 8, L..sec_end0 +; ASM64-NEXT: .byte 0 # End sequence +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: .byte 1 +; ASM64-NEXT: L..debug_line_end0: diff --git a/test/DebugInfo/XCOFF/explicit-section.ll b/test/DebugInfo/XCOFF/explicit-section.ll new file mode 100644 index 00000000000..cf6caa236b1 --- /dev/null +++ b/test/DebugInfo/XCOFF/explicit-section.ll @@ -0,0 +1,338 @@ + +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | \ +; RUN: FileCheck %s + +source_filename = "2.c" +target datalayout = "E-m:a-p:32:32-i64:64-n32" + +; Function Attrs: noinline nounwind optnone +define i32 @bar() #0 !dbg !8 { +entry: + ret i32 1, !dbg !13 +} + +; Function Attrs: noinline nounwind optnone +define i32 @main() #0 section "explicit_main_sec" !dbg !14 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + %call = call i32 @bar(), !dbg !15 + ret i32 %call, !dbg !16 +} + +!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 13.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "2.c", directory: "debug") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 3} +!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 13.0.0"} +!8 = distinct !DISubprogram(name: "bar", scope: !9, file: !9, line: 1, type: !10, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!9 = !DIFile(filename: "2.c", directory: "debug") +!10 = !DISubroutineType(types: !11) +!11 = !{!12} +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !DILocation(line: 1, column: 12, scope: !8) +!14 = distinct !DISubprogram(name: "main", scope: !9, file: !9, line: 2, type: !10, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!15 = !DILocation(line: 3, column: 10, scope: !14) +!16 = !DILocation(line: 3, column: 3, scope: !14) + +; CHECK: .csect .text[PR],2 +; CHECK-NEXT: .file "2.c" +; CHECK-NEXT: .globl bar[DS] # -- Begin function bar +; CHECK-NEXT: .globl .bar +; CHECK-NEXT: .align 2 +; CHECK-NEXT: .csect bar[DS],2 +; CHECK-NEXT: .vbyte 4, .bar # @bar +; CHECK-NEXT: .vbyte 4, TOC[TC0] +; CHECK-NEXT: .vbyte 4, 0 +; CHECK-NEXT: .csect .text[PR],2 +; CHECK-NEXT: .bar: +; CHECK-NEXT: L..func_begin0: +; CHECK-NEXT: # %bb.0: # %entry +; CHECK-NEXT: L..tmp0: +; CHECK-NEXT: L..tmp1: +; CHECK-NEXT: li 3, 1 +; CHECK-NEXT: blr +; CHECK-NEXT: L..tmp2: +; CHECK-NEXT: L..bar0: +; CHECK-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; CHECK-NEXT: .byte 0x00 # Version = 0 +; CHECK-NEXT: .byte 0x09 # Language = CPlusPlus +; CHECK-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; CHECK-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; CHECK-NEXT: # -HasControlledStorage, -IsTOCless +; CHECK-NEXT: # -IsFloatingPointPresent +; CHECK-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; CHECK-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; CHECK-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +; CHECK-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; CHECK-NEXT: .byte 0x00 # -HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; CHECK-NEXT: .byte 0x00 # NumberOfFixedParms = 0 +; CHECK-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; CHECK-NEXT: .vbyte 4, L..bar0-.bar # Function size +; CHECK-NEXT: .vbyte 2, 0x0003 # Function name len = 3 +; CHECK-NEXT: .byte 'b,'a,'r # Function Name +; CHECK-NEXT: L..func_end0: +; CHECK-NEXT: # -- End function +; CHECK-NEXT: .csect explicit_main_sec[PR],2 +; CHECK-NEXT: .globl main[DS] # -- Begin function main +; CHECK-NEXT: .globl .main +; CHECK-NEXT: .align 2 +; CHECK-NEXT: .csect main[DS],2 +; CHECK-NEXT: .vbyte 4, .main # @main +; CHECK-NEXT: .vbyte 4, TOC[TC0] +; CHECK-NEXT: .vbyte 4, 0 +; CHECK-NEXT: .csect explicit_main_sec[PR],2 +; CHECK-NEXT: .main: +; CHECK-NEXT: L..func_begin1: +; CHECK-NEXT: # %bb.0: # %entry +; CHECK-NEXT: L..tmp3: +; CHECK-NEXT: mflr 0 +; CHECK-NEXT: stw 0, 8(1) +; CHECK-NEXT: stwu 1, -64(1) +; CHECK-NEXT: li 3, 0 +; CHECK-NEXT: stw 3, 60(1) +; CHECK-NEXT: L..tmp4: +; CHECK-NEXT: L..tmp5: +; CHECK-NEXT: bl .bar +; CHECK-NEXT: nop +; CHECK-NEXT: L..tmp6: +; CHECK-NEXT: addi 1, 1, 64 +; CHECK-NEXT: lwz 0, 8(1) +; CHECK-NEXT: mtlr 0 +; CHECK-NEXT: blr +; CHECK-NEXT: L..tmp7: +; CHECK-NEXT: L..main0: +; CHECK-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; CHECK-NEXT: .byte 0x00 # Version = 0 +; CHECK-NEXT: .byte 0x09 # Language = CPlusPlus +; CHECK-NEXT: .byte 0x22 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; CHECK-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; CHECK-NEXT: # -HasControlledStorage, -IsTOCless +; CHECK-NEXT: # +IsFloatingPointPresent +; CHECK-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; CHECK-NEXT: .byte 0x41 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; CHECK-NEXT: # OnConditionDirective = 0, -IsCRSaved, +IsLRSaved +; CHECK-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; CHECK-NEXT: .byte 0x00 # -HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; CHECK-NEXT: .byte 0x00 # NumberOfFixedParms = 0 +; CHECK-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; CHECK-NEXT: .vbyte 4, L..main0-.main # Function size +; CHECK-NEXT: .vbyte 2, 0x0004 # Function name len = 4 +; CHECK-NEXT: .byte 'm,'a,'i,'n # Function Name +; CHECK-NEXT: L..func_end1: +; CHECK-NEXT: # -- End function +; CHECK-NEXT: L..sec_end0: +; CHECK: .dwsect 0x60000 +; CHECK-NEXT: L...dwabrev: +; CHECK-NEXT: .byte 1 # Abbreviation Code +; CHECK-NEXT: .byte 17 # DW_TAG_compile_unit +; CHECK-NEXT: .byte 1 # DW_CHILDREN_yes +; CHECK-NEXT: .byte 37 # DW_AT_producer +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 19 # DW_AT_language +; CHECK-NEXT: .byte 5 # DW_FORM_data2 +; CHECK-NEXT: .byte 3 # DW_AT_name +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 16 # DW_AT_stmt_list +; CHECK-NEXT: .byte 6 # DW_FORM_data4 +; CHECK-NEXT: .byte 27 # DW_AT_comp_dir +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 17 # DW_AT_low_pc +; CHECK-NEXT: .byte 1 # DW_FORM_addr +; CHECK-NEXT: .byte 85 # DW_AT_ranges +; CHECK-NEXT: .byte 6 # DW_FORM_data4 +; CHECK-NEXT: .byte 0 # EOM(1) +; CHECK-NEXT: .byte 0 # EOM(2) +; CHECK-NEXT: .byte 2 # Abbreviation Code +; CHECK-NEXT: .byte 46 # DW_TAG_subprogram +; CHECK-NEXT: .byte 0 # DW_CHILDREN_no +; CHECK-NEXT: .byte 17 # DW_AT_low_pc +; CHECK-NEXT: .byte 1 # DW_FORM_addr +; CHECK-NEXT: .byte 18 # DW_AT_high_pc +; CHECK-NEXT: .byte 1 # DW_FORM_addr +; CHECK-NEXT: .byte 64 # DW_AT_frame_base +; CHECK-NEXT: .byte 10 # DW_FORM_block1 +; CHECK-NEXT: .byte 3 # DW_AT_name +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 58 # DW_AT_decl_file +; CHECK-NEXT: .byte 11 # DW_FORM_data1 +; CHECK-NEXT: .byte 59 # DW_AT_decl_line +; CHECK-NEXT: .byte 11 # DW_FORM_data1 +; CHECK-NEXT: .byte 73 # DW_AT_type +; CHECK-NEXT: .byte 19 # DW_FORM_ref4 +; CHECK-NEXT: .byte 63 # DW_AT_external +; CHECK-NEXT: .byte 12 # DW_FORM_flag +; CHECK-NEXT: .byte 0 # EOM(1) +; CHECK-NEXT: .byte 0 # EOM(2) +; CHECK-NEXT: .byte 3 # Abbreviation Code +; CHECK-NEXT: .byte 36 # DW_TAG_base_type +; CHECK-NEXT: .byte 0 # DW_CHILDREN_no +; CHECK-NEXT: .byte 3 # DW_AT_name +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 62 # DW_AT_encoding +; CHECK-NEXT: .byte 11 # DW_FORM_data1 +; CHECK-NEXT: .byte 11 # DW_AT_byte_size +; CHECK-NEXT: .byte 11 # DW_FORM_data1 +; CHECK-NEXT: .byte 0 # EOM(1) +; CHECK-NEXT: .byte 0 # EOM(2) +; CHECK-NEXT: .byte 0 # EOM(3) +; CHECK: .dwsect 0x10000 +; CHECK-NEXT: L...dwinfo: +; CHECK-NEXT: L..cu_begin0: +; CHECK-NEXT: .vbyte 2, 3 # DWARF version number +; CHECK-NEXT: .vbyte 4, L...dwabrev # Offset Into Abbrev. Section +; CHECK-NEXT: .byte 4 # Address Size (in bytes) +; CHECK-NEXT: .byte 1 # Abbrev [1] 0xb:0x4f DW_TAG_compile_unit +; CHECK-NEXT: .vbyte 4, L..info_string0 # DW_AT_producer +; CHECK-NEXT: .vbyte 2, 12 # DW_AT_language +; CHECK-NEXT: .vbyte 4, L..info_string1 # DW_AT_name +; CHECK-NEXT: .vbyte 4, L..line_table_start0 # DW_AT_stmt_list +; CHECK-NEXT: .vbyte 4, L..info_string2 # DW_AT_comp_dir +; CHECK-NEXT: .vbyte 4, 0 # DW_AT_low_pc +; CHECK-NEXT: .vbyte 4, L..debug_ranges0 # DW_AT_ranges +; CHECK-NEXT: .byte 2 # Abbrev [2] 0x26:0x16 DW_TAG_subprogram +; CHECK-NEXT: .vbyte 4, L..func_begin0 # DW_AT_low_pc +; CHECK-NEXT: .vbyte 4, L..func_end0 # DW_AT_high_pc +; CHECK-NEXT: .byte 1 # DW_AT_frame_base +; CHECK-NEXT: .byte 81 +; CHECK-NEXT: .vbyte 4, L..info_string3 # DW_AT_name +; CHECK-NEXT: .byte 1 # DW_AT_decl_file +; CHECK-NEXT: .byte 1 # DW_AT_decl_line +; CHECK-NEXT: .vbyte 4, 82 # DW_AT_type +; CHECK-NEXT: .byte 1 # DW_AT_external +; CHECK-NEXT: .byte 2 # Abbrev [2] 0x3c:0x16 DW_TAG_subprogram +; CHECK-NEXT: .vbyte 4, L..func_begin1 # DW_AT_low_pc +; CHECK-NEXT: .vbyte 4, L..func_end1 # DW_AT_high_pc +; CHECK-NEXT: .byte 1 # DW_AT_frame_base +; CHECK-NEXT: .byte 81 +; CHECK-NEXT: .vbyte 4, L..info_string5 # DW_AT_name +; CHECK-NEXT: .byte 1 # DW_AT_decl_file +; CHECK-NEXT: .byte 2 # DW_AT_decl_line +; CHECK-NEXT: .vbyte 4, 82 # DW_AT_type +; CHECK-NEXT: .byte 1 # DW_AT_external +; CHECK-NEXT: .byte 3 # Abbrev [3] 0x52:0x7 DW_TAG_base_type +; CHECK-NEXT: .vbyte 4, L..info_string4 # DW_AT_name +; CHECK-NEXT: .byte 5 # DW_AT_encoding +; CHECK-NEXT: .byte 4 # DW_AT_byte_size +; CHECK-NEXT: .byte 0 # End Of Children Mark +; CHECK-NEXT: L..debug_info_end0: +; CHECK: .dwsect 0x80000 +; CHECK-NEXT: L...dwrnges: +; CHECK-NEXT: L..debug_ranges0: +; CHECK-NEXT: .vbyte 4, L..func_begin0 +; CHECK-NEXT: .vbyte 4, L..func_end0 +; CHECK-NEXT: .vbyte 4, L..func_begin1 +; CHECK-NEXT: .vbyte 4, L..func_end1 +; CHECK-NEXT: .vbyte 4, 0 +; CHECK-NEXT: .vbyte 4, 0 +; CHECK: .dwsect 0x70000 +; CHECK-NEXT: L...dwstr: +; CHECK-NEXT: L..info_string0: +; CHECK-NEXT: .byte 'c,'l,'a,'n,'g,' ,'v,'e,'r,'s,'i,'o,'n,' ,'1,'3,'.,'0,'.,'0,0000 # string offset=0 +; CHECK-NEXT: L..info_string1: +; CHECK-NEXT: .byte '2,'.,'c,0000 # string offset=21 +; CHECK-NEXT: L..info_string2: +; CHECK-NEXT: .byte 'd,'e,'b,'u,'g,0000 # string offset=25 +; CHECK-NEXT: L..info_string3: +; CHECK-NEXT: .byte 'b,'a,'r,0000 # string offset=31 +; CHECK-NEXT: L..info_string4: +; CHECK-NEXT: .byte 'i,'n,'t,0000 # string offset=35 +; CHECK-NEXT: L..info_string5: +; CHECK-NEXT: .byte 'm,'a,'i,'n,0000 # string offset=39 +; CHECK-NEXT: .toc +; CHECK: .dwsect 0x20000 +; CHECK-NEXT: L...dwline: +; CHECK-NEXT: L..debug_line_0: +; CHECK-NEXT: .set L..line_table_start0, L..debug_line_0-4 +; CHECK-NEXT: .vbyte 2, 3 +; CHECK-NEXT: .vbyte 4, L..tmp9-L..tmp8 +; CHECK-NEXT: L..tmp8: +; CHECK-NEXT: .byte 4 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte -5 +; CHECK-NEXT: .byte 14 +; CHECK-NEXT: .byte 13 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 'd,'e,'b,'u,'g +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte '2,'.,'c +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: L..tmp9: +; CHECK-NEXT: .byte 0 # Set address to L..tmp0 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp0 +; CHECK-NEXT: .byte 1 # Start sequence +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 12 +; CHECK-NEXT: .byte 10 +; CHECK-NEXT: .byte 0 # Set address to L..tmp1 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp1 +; CHECK-NEXT: .byte 3 # Advance line 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 # Set address to L..sec_end0 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..sec_end0 +; CHECK-NEXT: .byte 0 # End sequence +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 # Set address to L..tmp3 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp3 +; CHECK-NEXT: .byte 19 # Start sequence +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 10 +; CHECK-NEXT: .byte 10 +; CHECK-NEXT: .byte 0 # Set address to L..tmp5 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp5 +; CHECK-NEXT: .byte 3 # Advance line 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 3 +; CHECK-NEXT: .byte 6 +; CHECK-NEXT: .byte 0 # Set address to L..tmp6 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp6 +; CHECK-NEXT: .byte 3 # Advance line 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 # Set address to L..sec_end0 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..sec_end0 +; CHECK-NEXT: .byte 0 # End sequence +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: L..debug_line_end0: diff --git a/test/DebugInfo/XCOFF/function-sections.ll b/test/DebugInfo/XCOFF/function-sections.ll new file mode 100644 index 00000000000..7e5f983c496 --- /dev/null +++ b/test/DebugInfo/XCOFF/function-sections.ll @@ -0,0 +1,315 @@ + +; RUN: llc -mtriple powerpc-ibm-aix-xcoff -function-sections \ +; RUN: < %s | FileCheck %s + +source_filename = "1.c" +target datalayout = "E-m:a-p:32:32-i64:64-n32" + +; Function Attrs: noinline nounwind optnone +define i32 @foo() #0 !dbg !8 { +entry: + ret i32 0, !dbg !12 +} + +; Function Attrs: noinline nounwind optnone +define i32 @bar() #0 !dbg !13 { +entry: + ret i32 1, !dbg !14 +} + +!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 13.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 3} +!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 13.0.0"} +!8 = distinct !DISubprogram(name: "foo", 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) +!13 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 6, type: !9, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!14 = !DILocation(line: 8, column: 3, scope: !13) + +; CHECK: .csect .text[PR],2 +; CHECK-NEXT: .file "1.c" +; CHECK-NEXT: .csect .foo[PR],2 +; CHECK-NEXT: .globl foo[DS] # -- Begin function foo +; CHECK-NEXT: .globl .foo[PR] +; CHECK-NEXT: .align 2 +; CHECK-NEXT: .csect foo[DS],2 +; CHECK-NEXT: .vbyte 4, .foo[PR] # @foo +; CHECK-NEXT: .vbyte 4, TOC[TC0] +; CHECK-NEXT: .vbyte 4, 0 +; CHECK-NEXT: .csect .foo[PR],2 +; CHECK-NEXT: L..func_begin0: +; CHECK-NEXT: # %bb.0: # %entry +; CHECK-NEXT: L..tmp0: +; CHECK-NEXT: L..tmp1: +; CHECK-NEXT: li 3, 0 +; CHECK-NEXT: blr +; CHECK-NEXT: L..tmp2: +; CHECK-NEXT: L..foo0: +; CHECK-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; CHECK-NEXT: .byte 0x00 # Version = 0 +; CHECK-NEXT: .byte 0x09 # Language = CPlusPlus +; CHECK-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; CHECK-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; CHECK-NEXT: # -HasControlledStorage, -IsTOCless +; CHECK-NEXT: # -IsFloatingPointPresent +; CHECK-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; CHECK-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; CHECK-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +; CHECK-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; CHECK-NEXT: .byte 0x00 # -HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; CHECK-NEXT: .byte 0x00 # NumberOfFixedParms = 0 +; CHECK-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; CHECK-NEXT: .vbyte 4, L..foo0-.foo[PR] # Function size +; CHECK-NEXT: .vbyte 2, 0x0003 # Function name len = 3 +; CHECK-NEXT: .byte 'f,'o,'o # Function Name +; CHECK-NEXT: L..func_end0: +; CHECK-NEXT: # -- End function +; CHECK-NEXT: .csect .bar[PR],2 +; CHECK-NEXT: .globl bar[DS] # -- Begin function bar +; CHECK-NEXT: .globl .bar[PR] +; CHECK-NEXT: .align 2 +; CHECK-NEXT: .csect bar[DS],2 +; CHECK-NEXT: .vbyte 4, .bar[PR] # @bar +; CHECK-NEXT: .vbyte 4, TOC[TC0] +; CHECK-NEXT: .vbyte 4, 0 +; CHECK-NEXT: .csect .bar[PR],2 +; CHECK-NEXT: L..func_begin1: +; CHECK-NEXT: # %bb.0: # %entry +; CHECK-NEXT: L..tmp3: +; CHECK-NEXT: L..tmp4: +; CHECK-NEXT: li 3, 1 +; CHECK-NEXT: blr +; CHECK-NEXT: L..tmp5: +; CHECK-NEXT: L..bar0: +; CHECK-NEXT: .vbyte 4, 0x00000000 # Traceback table begin +; CHECK-NEXT: .byte 0x00 # Version = 0 +; CHECK-NEXT: .byte 0x09 # Language = CPlusPlus +; CHECK-NEXT: .byte 0x20 # -IsGlobaLinkage, -IsOutOfLineEpilogOrPrologue +; CHECK-NEXT: # +HasTraceBackTableOffset, -IsInternalProcedure +; CHECK-NEXT: # -HasControlledStorage, -IsTOCless +; CHECK-NEXT: # -IsFloatingPointPresent +; CHECK-NEXT: # -IsFloatingPointOperationLogOrAbortEnabled +; CHECK-NEXT: .byte 0x40 # -IsInterruptHandler, +IsFunctionNamePresent, -IsAllocaUsed +; CHECK-NEXT: # OnConditionDirective = 0, -IsCRSaved, -IsLRSaved +; CHECK-NEXT: .byte 0x80 # +IsBackChainStored, -IsFixup, NumOfFPRsSaved = 0 +; CHECK-NEXT: .byte 0x00 # -HasVectorInfo, -HasExtensionTable, NumOfGPRsSaved = 0 +; CHECK-NEXT: .byte 0x00 # NumberOfFixedParms = 0 +; CHECK-NEXT: .byte 0x01 # NumberOfFPParms = 0, +HasParmsOnStack +; CHECK-NEXT: .vbyte 4, L..bar0-.bar[PR] # Function size +; CHECK-NEXT: .vbyte 2, 0x0003 # Function name len = 3 +; CHECK-NEXT: .byte 'b,'a,'r # Function Name +; CHECK-NEXT: L..func_end1: +; CHECK-NEXT: # -- End function +; CHECK-NEXT: L..sec_end0: +; CHECK: .dwsect 0x60000 +; CHECK-NEXT: L...dwabrev: +; CHECK-NEXT: .byte 1 # Abbreviation Code +; CHECK-NEXT: .byte 17 # DW_TAG_compile_unit +; CHECK-NEXT: .byte 1 # DW_CHILDREN_yes +; CHECK-NEXT: .byte 37 # DW_AT_producer +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 19 # DW_AT_language +; CHECK-NEXT: .byte 5 # DW_FORM_data2 +; CHECK-NEXT: .byte 3 # DW_AT_name +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 16 # DW_AT_stmt_list +; CHECK-NEXT: .byte 6 # DW_FORM_data4 +; CHECK-NEXT: .byte 27 # DW_AT_comp_dir +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 17 # DW_AT_low_pc +; CHECK-NEXT: .byte 1 # DW_FORM_addr +; CHECK-NEXT: .byte 85 # DW_AT_ranges +; CHECK-NEXT: .byte 6 # DW_FORM_data4 +; CHECK-NEXT: .byte 0 # EOM(1) +; CHECK-NEXT: .byte 0 # EOM(2) +; CHECK-NEXT: .byte 2 # Abbreviation Code +; CHECK-NEXT: .byte 46 # DW_TAG_subprogram +; CHECK-NEXT: .byte 0 # DW_CHILDREN_no +; CHECK-NEXT: .byte 17 # DW_AT_low_pc +; CHECK-NEXT: .byte 1 # DW_FORM_addr +; CHECK-NEXT: .byte 18 # DW_AT_high_pc +; CHECK-NEXT: .byte 1 # DW_FORM_addr +; CHECK-NEXT: .byte 64 # DW_AT_frame_base +; CHECK-NEXT: .byte 10 # DW_FORM_block1 +; CHECK-NEXT: .byte 3 # DW_AT_name +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 58 # DW_AT_decl_file +; CHECK-NEXT: .byte 11 # DW_FORM_data1 +; CHECK-NEXT: .byte 59 # DW_AT_decl_line +; CHECK-NEXT: .byte 11 # DW_FORM_data1 +; CHECK-NEXT: .byte 39 # DW_AT_prototyped +; CHECK-NEXT: .byte 12 # DW_FORM_flag +; CHECK-NEXT: .byte 73 # DW_AT_type +; CHECK-NEXT: .byte 19 # DW_FORM_ref4 +; CHECK-NEXT: .byte 63 # DW_AT_external +; CHECK-NEXT: .byte 12 # DW_FORM_flag +; CHECK-NEXT: .byte 0 # EOM(1) +; CHECK-NEXT: .byte 0 # EOM(2) +; CHECK-NEXT: .byte 3 # Abbreviation Code +; CHECK-NEXT: .byte 36 # DW_TAG_base_type +; CHECK-NEXT: .byte 0 # DW_CHILDREN_no +; CHECK-NEXT: .byte 3 # DW_AT_name +; CHECK-NEXT: .byte 14 # DW_FORM_strp +; CHECK-NEXT: .byte 62 # DW_AT_encoding +; CHECK-NEXT: .byte 11 # DW_FORM_data1 +; CHECK-NEXT: .byte 11 # DW_AT_byte_size +; CHECK-NEXT: .byte 11 # DW_FORM_data1 +; CHECK-NEXT: .byte 0 # EOM(1) +; CHECK-NEXT: .byte 0 # EOM(2) +; CHECK-NEXT: .byte 0 # EOM(3) +; CHECK: .dwsect 0x10000 +; CHECK-NEXT: L...dwinfo: +; CHECK-NEXT: L..cu_begin0: +; CHECK-NEXT: .vbyte 2, 3 # DWARF version number +; CHECK-NEXT: .vbyte 4, L...dwabrev # Offset Into Abbrev. Section +; CHECK-NEXT: .byte 4 # Address Size (in bytes) +; CHECK-NEXT: .byte 1 # Abbrev [1] 0xb:0x51 DW_TAG_compile_unit +; CHECK-NEXT: .vbyte 4, L..info_string0 # DW_AT_producer +; CHECK-NEXT: .vbyte 2, 12 # DW_AT_language +; CHECK-NEXT: .vbyte 4, L..info_string1 # DW_AT_name +; CHECK-NEXT: .vbyte 4, L..line_table_start0 # DW_AT_stmt_list +; CHECK-NEXT: .vbyte 4, L..info_string2 # DW_AT_comp_dir +; CHECK-NEXT: .vbyte 4, 0 # DW_AT_low_pc +; CHECK-NEXT: .vbyte 4, L..debug_ranges0 # DW_AT_ranges +; CHECK-NEXT: .byte 2 # Abbrev [2] 0x26:0x17 DW_TAG_subprogram +; CHECK-NEXT: .vbyte 4, L..func_begin0 # DW_AT_low_pc +; CHECK-NEXT: .vbyte 4, L..func_end0 # DW_AT_high_pc +; CHECK-NEXT: .byte 1 # DW_AT_frame_base +; CHECK-NEXT: .byte 81 +; CHECK-NEXT: .vbyte 4, L..info_string3 # DW_AT_name +; CHECK-NEXT: .byte 1 # DW_AT_decl_file +; CHECK-NEXT: .byte 1 # DW_AT_decl_line +; CHECK-NEXT: .byte 1 # DW_AT_prototyped +; CHECK-NEXT: .vbyte 4, 84 # DW_AT_type +; CHECK-NEXT: .byte 1 # DW_AT_external +; CHECK-NEXT: .byte 2 # Abbrev [2] 0x3d:0x17 DW_TAG_subprogram +; CHECK-NEXT: .vbyte 4, L..func_begin1 # DW_AT_low_pc +; CHECK-NEXT: .vbyte 4, L..func_end1 # DW_AT_high_pc +; CHECK-NEXT: .byte 1 # DW_AT_frame_base +; CHECK-NEXT: .byte 81 +; CHECK-NEXT: .vbyte 4, L..info_string5 # DW_AT_name +; CHECK-NEXT: .byte 1 # DW_AT_decl_file +; CHECK-NEXT: .byte 6 # DW_AT_decl_line +; CHECK-NEXT: .byte 1 # DW_AT_prototyped +; CHECK-NEXT: .vbyte 4, 84 # DW_AT_type +; CHECK-NEXT: .byte 1 # DW_AT_external +; CHECK-NEXT: .byte 3 # Abbrev [3] 0x54:0x7 DW_TAG_base_type +; CHECK-NEXT: .vbyte 4, L..info_string4 # DW_AT_name +; CHECK-NEXT: .byte 5 # DW_AT_encoding +; CHECK-NEXT: .byte 4 # DW_AT_byte_size +; CHECK-NEXT: .byte 0 # End Of Children Mark +; CHECK-NEXT: L..debug_info_end0: +; CHECK: .dwsect 0x80000 +; CHECK-NEXT: L...dwrnges: +; CHECK-NEXT: L..debug_ranges0: +; CHECK-NEXT: .vbyte 4, L..func_begin0 +; CHECK-NEXT: .vbyte 4, L..func_end0 +; CHECK-NEXT: .vbyte 4, L..func_begin1 +; CHECK-NEXT: .vbyte 4, L..func_end1 +; CHECK-NEXT: .vbyte 4, 0 +; CHECK-NEXT: .vbyte 4, 0 +; CHECK: .dwsect 0x70000 +; CHECK-NEXT: L...dwstr: +; CHECK-NEXT: L..info_string0: +; CHECK-NEXT: .byte 'c,'l,'a,'n,'g,' ,'v,'e,'r,'s,'i,'o,'n,' ,'1,'3,'.,'0,'.,'0,0000 # string offset=0 +; CHECK-NEXT: L..info_string1: +; CHECK-NEXT: .byte '1,'.,'c,0000 # string offset=21 +; CHECK-NEXT: L..info_string2: +; CHECK-NEXT: .byte 'd,'e,'b,'u,'g,0000 # string offset=25 +; CHECK-NEXT: L..info_string3: +; CHECK-NEXT: .byte 'f,'o,'o,0000 # string offset=31 +; CHECK-NEXT: L..info_string4: +; CHECK-NEXT: .byte 'i,'n,'t,0000 # string offset=35 +; CHECK-NEXT: L..info_string5: +; CHECK-NEXT: .byte 'b,'a,'r,0000 # string offset=39 +; CHECK-NEXT: .toc +; CHECK: .dwsect 0x20000 +; CHECK-NEXT: L...dwline: +; CHECK-NEXT: L..debug_line_0: +; CHECK-NEXT: .set L..line_table_start0, L..debug_line_0-4 +; CHECK-NEXT: .vbyte 2, 3 +; CHECK-NEXT: .vbyte 4, L..tmp7-L..tmp6 +; CHECK-NEXT: L..tmp6: +; CHECK-NEXT: .byte 4 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte -5 +; CHECK-NEXT: .byte 14 +; CHECK-NEXT: .byte 13 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 'd,'e,'b,'u,'g +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte '1,'.,'c +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: L..tmp7: +; CHECK-NEXT: .byte 0 # Set address to L..tmp0 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp0 +; CHECK-NEXT: .byte 19 # Start sequence +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 3 +; CHECK-NEXT: .byte 10 +; CHECK-NEXT: .byte 0 # Set address to L..tmp1 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp1 +; CHECK-NEXT: .byte 3 # Advance line 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 # Set address to L..sec_end0 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..sec_end0 +; CHECK-NEXT: .byte 0 # End sequence +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 # Set address to L..tmp3 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp3 +; CHECK-NEXT: .byte 24 # Start sequence +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 3 +; CHECK-NEXT: .byte 10 +; CHECK-NEXT: .byte 0 # Set address to L..tmp4 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..tmp4 +; CHECK-NEXT: .byte 3 # Advance line 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 # Set address to L..sec_end0 +; CHECK-NEXT: .byte 5 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .vbyte 4, L..sec_end0 +; CHECK-NEXT: .byte 0 # End sequence +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: L..debug_line_end0: diff --git a/test/DebugInfo/XCOFF/lit.local.cfg b/test/DebugInfo/XCOFF/lit.local.cfg new file mode 100644 index 00000000000..091332439b1 --- /dev/null +++ b/test/DebugInfo/XCOFF/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'PowerPC' in config.root.targets: + config.unsupported = True