[XCOFF][DebugInfo] support DWARF for XCOFF for assembly output.
authorChen Zheng <czhengsz@cn.ibm.com>
Fri, 5 Mar 2021 01:47:41 +0000 (20:47 -0500)
committerChen Zheng <czhengsz@cn.ibm.com>
Fri, 5 Mar 2021 02:07:52 +0000 (21:07 -0500)
Reviewed By: jasonliu

Differential Revision: https://reviews.llvm.org/D95518

22 files changed:
llvm/include/llvm/MC/MCAsmInfo.h
llvm/include/llvm/MC/MCContext.h
llvm/include/llvm/MC/MCDwarf.h
llvm/include/llvm/MC/MCObjectStreamer.h
llvm/include/llvm/MC/MCSectionXCOFF.h
llvm/include/llvm/MC/MCStreamer.h
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
llvm/lib/MC/MCAsmInfoXCOFF.cpp
llvm/lib/MC/MCAsmStreamer.cpp
llvm/lib/MC/MCContext.cpp
llvm/lib/MC/MCDwarf.cpp
llvm/lib/MC/MCObjectFileInfo.cpp
llvm/lib/MC/MCObjectStreamer.cpp
llvm/lib/MC/MCSectionXCOFF.cpp
llvm/lib/MC/MCStreamer.cpp
llvm/lib/MC/MCSymbolXCOFF.cpp
llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
llvm/test/DebugInfo/XCOFF/empty.ll [new file with mode: 0644]
llvm/test/DebugInfo/XCOFF/explicit-section.ll [new file with mode: 0644]
llvm/test/DebugInfo/XCOFF/function-sections.ll [new file with mode: 0644]
llvm/test/DebugInfo/XCOFF/lit.local.cfg [new file with mode: 0644]

index 9b2ac55..309932b 100644 (file)
@@ -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<MCCFIInstruction> &getInitialFrameState() const {
index 33874e8..106763c 100644 (file)
@@ -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<XCOFF::CsectProperties> CsectProp = None,
-                    bool MultiSymbolsAllowed = false,
-                    const char *BeginSymName = nullptr);
+    MCSectionXCOFF *getXCOFFSection(
+        StringRef Section, SectionKind K,
+        Optional<XCOFF::CsectProperties> CsectProp = None,
+        bool MultiSymbolsAllowed = false, const char *BeginSymName = nullptr,
+        Optional<XCOFF::DwarfSectionSubtypeFlags> DwarfSubtypeFlags = None);
 
     // Create and save a copy of STI and return a reference to the copy.
     MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
index 5bf6496..625e83a 100644 (file)
@@ -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<MCDwarfLineStr> &LineStr) const;
 
   Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
index a00000b..a0169c4 100644 (file)
@@ -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,
index 768e398..27c06a2 100644 (file)
@@ -35,6 +35,7 @@ class MCSectionXCOFF final : public MCSection {
   Optional<XCOFF::CsectProperties> CsectProp;
   MCSymbolXCOFF *const QualName;
   StringRef SymbolTableName;
+  Optional<XCOFF::DwarfSectionSubtypeFlags> 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<XCOFF::DwarfSectionSubtypeFlags> getDwarfSubtypeFlags() const {
+    return DwarfSubtypeFlags;
+  }
 };
 
 } // end namespace llvm
index 7f50995..4156d69 100644 (file)
@@ -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
index 438492e..beed2a5 100644 (file)
@@ -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();
 
index 2f8bc6a..a23a71b 100644 (file)
@@ -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";
index 10d7255..e82ad28 100644 (file)
@@ -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<unsigned> 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<formatted_raw_ostream> OS,
                                     bool isVerboseAsm, bool useDwarfDirectory,
index b0eb470..cf7e38f 100644 (file)
@@ -686,15 +686,20 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind Kind,
   return Result;
 }
 
-MCSectionXCOFF *
-MCContext::getXCOFFSection(StringRef Section, SectionKind Kind,
-                           Optional<XCOFF::CsectProperties> CsectProp,
-                           bool MultiSymbolsAllowed, const char *BeginSymName) {
+MCSectionXCOFF *MCContext::getXCOFFSection(
+    StringRef Section, SectionKind Kind,
+    Optional<XCOFF::CsectProperties> CsectProp, bool MultiSymbolsAllowed,
+    const char *BeginSymName,
+    Optional<XCOFF::DwarfSectionSubtypeFlags> 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<MCSymbolXCOFF>(getOrCreateSymbol(
-      CachedName + "[" + XCOFF::getMappingClassString(CsectProp->MappingClass) +
-      "]"));
+  MCSymbolXCOFF *QualName = nullptr;
+  // Debug section don't have storage class attribute.
+  if (IsDwarfSec)
+    QualName = cast<MCSymbolXCOFF>(getOrCreateSymbol(CachedName));
+  else
+    QualName = cast<MCSymbolXCOFF>(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();
index df04f11..6c23d33 100644 (file)
@@ -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<MCDwarfLineStr> &LineStr) const {
   MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
 
index 06c1ae6..155104c 100644 (file)
@@ -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,
index 1c23d31..299f2a7 100644 (file)
@@ -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);
index 8c01f7f..2adddd3 100644 (file)
@@ -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.");
 }
 
index b2fc542..afaa570 100644 (file)
@@ -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);
index b9dd290..b4c96a1 100644 (file)
@@ -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.");
index 2b76af2..b0f5267 100644 (file)
@@ -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;
 }
index ddfca2a..4e307df 100644 (file)
@@ -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/llvm/test/DebugInfo/XCOFF/empty.ll b/llvm/test/DebugInfo/XCOFF/empty.ll
new file mode 100644 (file)
index 0000000..1e65797
--- /dev/null
@@ -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/llvm/test/DebugInfo/XCOFF/explicit-section.ll b/llvm/test/DebugInfo/XCOFF/explicit-section.ll
new file mode 100644 (file)
index 0000000..cf6caa2
--- /dev/null
@@ -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/llvm/test/DebugInfo/XCOFF/function-sections.ll b/llvm/test/DebugInfo/XCOFF/function-sections.ll
new file mode 100644 (file)
index 0000000..7e5f983
--- /dev/null
@@ -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/llvm/test/DebugInfo/XCOFF/lit.local.cfg b/llvm/test/DebugInfo/XCOFF/lit.local.cfg
new file mode 100644 (file)
index 0000000..0913324
--- /dev/null
@@ -0,0 +1,2 @@
+if not 'PowerPC' in config.root.targets:
+    config.unsupported = True