//===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements XCOFF object file writer information.
//
//===----------------------------------------------------------------------===//

#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionXCOFF.h"
#include "llvm/MC/MCSymbolXCOFF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCXCOFFObjectWriter.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"

#include <deque>
#include <map>

using namespace llvm;

// An XCOFF object file has a limited set of predefined sections. The most
// important ones for us (right now) are:
// .text --> contains program code and read-only data.
// .data --> contains initialized data, function descriptors, and the TOC.
// .bss  --> contains uninitialized data.
// Each of these sections is composed of 'Control Sections'. A Control Section
// is more commonly referred to as a csect. A csect is an indivisible unit of
// code or data, and acts as a container for symbols. A csect is mapped
// into a section based on its storage-mapping class, with the exception of
// XMC_RW which gets mapped to either .data or .bss based on whether it's
// explicitly initialized or not.
//
// We don't represent the sections in the MC layer as there is nothing
// interesting about them at at that level: they carry information that is
// only relevant to the ObjectWriter, so we materialize them in this class.
namespace {

constexpr unsigned DefaultSectionAlign = 4;
constexpr int16_t MaxSectionIndex = INT16_MAX;

// Packs the csect's alignment and type into a byte.
uint8_t getEncodedType(const MCSectionXCOFF *);

struct XCOFFRelocation {
  uint32_t SymbolTableIndex;
  uint32_t FixupOffsetInCsect;
  uint8_t SignAndSize;
  uint8_t Type;
};

// Wrapper around an MCSymbolXCOFF.
struct Symbol {
  const MCSymbolXCOFF *const MCSym;
  uint32_t SymbolTableIndex;

  XCOFF::VisibilityType getVisibilityType() const {
    return MCSym->getVisibilityType();
  }

  XCOFF::StorageClass getStorageClass() const {
    return MCSym->getStorageClass();
  }
  StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
  Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
};

// Wrapper for an MCSectionXCOFF.
// It can be a Csect or debug section or DWARF section and so on.
struct XCOFFSection {
  const MCSectionXCOFF *const MCSec;
  uint32_t SymbolTableIndex;
  uint64_t Address;
  uint64_t Size;

  SmallVector<Symbol, 1> Syms;
  SmallVector<XCOFFRelocation, 1> Relocations;
  StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
  XCOFF::VisibilityType getVisibilityType() const {
    return MCSec->getVisibilityType();
  }
  XCOFFSection(const MCSectionXCOFF *MCSec)
      : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
};

// Type to be used for a container representing a set of csects with
// (approximately) the same storage mapping class. For example all the csects
// with a storage mapping class of `xmc_pr` will get placed into the same
// container.
using CsectGroup = std::deque<XCOFFSection>;
using CsectGroups = std::deque<CsectGroup *>;

// The basic section entry defination. This Section represents a section entry
// in XCOFF section header table.
struct SectionEntry {
  char Name[XCOFF::NameSize];
  // The physical/virtual address of the section. For an object file these
  // values are equivalent, except for in the overflow section header, where
  // the physical address specifies the number of relocation entries and the
  // virtual address specifies the number of line number entries.
  // TODO: Divide Address into PhysicalAddress and VirtualAddress when line
  // number entries are supported.
  uint64_t Address;
  uint64_t Size;
  uint64_t FileOffsetToData;
  uint64_t FileOffsetToRelocations;
  uint32_t RelocationCount;
  int32_t Flags;

  int16_t Index;

  virtual uint64_t advanceFileOffset(const uint64_t MaxRawDataSize,
                                     const uint64_t RawPointer) {
    FileOffsetToData = RawPointer;
    uint64_t NewPointer = RawPointer + Size;
    if (NewPointer > MaxRawDataSize)
      report_fatal_error("Section raw data overflowed this object file.");
    return NewPointer;
  }

  // XCOFF has special section numbers for symbols:
  // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
  // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
  // relocatable.
  //  0 Specifies N_UNDEF, an undefined external symbol.
  // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
  // hasn't been initialized.
  static constexpr int16_t UninitializedIndex =
      XCOFF::ReservedSectionNum::N_DEBUG - 1;

  SectionEntry(StringRef N, int32_t Flags)
      : Name(), Address(0), Size(0), FileOffsetToData(0),
        FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
        Index(UninitializedIndex) {
    assert(N.size() <= XCOFF::NameSize && "section name too long");
    memcpy(Name, N.data(), N.size());
  }

  virtual void reset() {
    Address = 0;
    Size = 0;
    FileOffsetToData = 0;
    FileOffsetToRelocations = 0;
    RelocationCount = 0;
    Index = UninitializedIndex;
  }

  virtual ~SectionEntry() = default;
};

// Represents the data related to a section excluding the csects that make up
// the raw data of the section. The csects are stored separately as not all
// sections contain csects, and some sections contain csects which are better
// stored separately, e.g. the .data section containing read-write, descriptor,
// TOCBase and TOC-entry csects.
struct CsectSectionEntry : public SectionEntry {
  // Virtual sections do not need storage allocated in the object file.
  const bool IsVirtual;

  // This is a section containing csect groups.
  CsectGroups Groups;

  CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
                    CsectGroups Groups)
      : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) {
    assert(N.size() <= XCOFF::NameSize && "section name too long");
    memcpy(Name, N.data(), N.size());
  }

  void reset() override {
    SectionEntry::reset();
    // Clear any csects we have stored.
    for (auto *Group : Groups)
      Group->clear();
  }

  virtual ~CsectSectionEntry() = default;
};

struct DwarfSectionEntry : public SectionEntry {
  // For DWARF section entry.
  std::unique_ptr<XCOFFSection> DwarfSect;

  // For DWARF section, we must use real size in the section header. MemorySize
  // is for the size the DWARF section occupies including paddings.
  uint32_t MemorySize;

  // TODO: Remove this override. Loadable sections (e.g., .text, .data) may need
  // to be aligned. Other sections generally don't need any alignment, but if
  // they're aligned, the RawPointer should be adjusted before writing the
  // section. Then a dwarf-specific function wouldn't be needed.
  uint64_t advanceFileOffset(const uint64_t MaxRawDataSize,
                             const uint64_t RawPointer) override {
    FileOffsetToData = RawPointer;
    uint64_t NewPointer = RawPointer + MemorySize;
    assert(NewPointer <= MaxRawDataSize &&
           "Section raw data overflowed this object file.");
    return NewPointer;
  }

  DwarfSectionEntry(StringRef N, int32_t Flags,
                    std::unique_ptr<XCOFFSection> Sect)
      : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)),
        MemorySize(0) {
    assert(DwarfSect->MCSec->isDwarfSect() &&
           "This should be a DWARF section!");
    assert(N.size() <= XCOFF::NameSize && "section name too long");
    memcpy(Name, N.data(), N.size());
  }

  DwarfSectionEntry(DwarfSectionEntry &&s) = default;

  virtual ~DwarfSectionEntry() = default;
};

struct ExceptionTableEntry {
  const MCSymbol *Trap;
  uint64_t TrapAddress = ~0ul;
  unsigned Lang;
  unsigned Reason;

  ExceptionTableEntry(const MCSymbol *Trap, unsigned Lang, unsigned Reason)
      : Trap(Trap), Lang(Lang), Reason(Reason) {}
};

struct ExceptionInfo {
  const MCSymbol *FunctionSymbol;
  unsigned FunctionSize;
  std::vector<ExceptionTableEntry> Entries;
};

struct ExceptionSectionEntry : public SectionEntry {
  std::map<const StringRef, ExceptionInfo> ExceptionTable;
  bool isDebugEnabled = false;

  ExceptionSectionEntry(StringRef N, int32_t Flags)
      : SectionEntry(N, Flags | XCOFF::STYP_EXCEPT) {
    assert(N.size() <= XCOFF::NameSize && "Section too long.");
    memcpy(Name, N.data(), N.size());
  }

  virtual ~ExceptionSectionEntry() = default;
};

struct CInfoSymInfo {
  // Name of the C_INFO symbol associated with the section
  std::string Name;
  std::string Metadata;
  // Offset into the start of the metadata in the section
  uint64_t Offset;

  CInfoSymInfo(std::string Name, std::string Metadata)
      : Name(Name), Metadata(Metadata) {}
  // Metadata needs to be padded out to an even word size.
  uint32_t paddingSize() const {
    return alignTo(Metadata.size(), sizeof(uint32_t)) - Metadata.size();
  };

  // Total size of the entry, including the 4 byte length
  uint32_t size() const {
    return Metadata.size() + paddingSize() + sizeof(uint32_t);
  };
};

struct CInfoSymSectionEntry : public SectionEntry {
  std::unique_ptr<CInfoSymInfo> Entry;

  CInfoSymSectionEntry(StringRef N, int32_t Flags) : SectionEntry(N, Flags) {}
  virtual ~CInfoSymSectionEntry() = default;
  void addEntry(std::unique_ptr<CInfoSymInfo> NewEntry) {
    Entry = std::move(NewEntry);
    Entry->Offset = sizeof(uint32_t);
    Size += Entry->size();
  }
  void reset() override {
    SectionEntry::reset();
    Entry.reset();
  }
};

class XCOFFWriter final : public XCOFFObjectWriter {
  uint32_t SymbolTableEntryCount = 0;
  uint64_t SymbolTableOffset = 0;
  uint16_t SectionCount = 0;
  uint32_t PaddingsBeforeDwarf = 0;
  bool HasVisibility = false;

  support::endian::Writer W;
  std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
  StringTableBuilder Strings;

  const uint64_t MaxRawDataSize =
      TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX;

  // Maps the MCSection representation to its corresponding XCOFFSection
  // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
  // from its containing MCSectionXCOFF.
  DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap;

  // Maps the MCSymbol representation to its corrresponding symbol table index.
  // Needed for relocation.
  DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;

  // CsectGroups. These store the csects which make up different parts of
  // the sections. Should have one for each set of csects that get mapped into
  // the same section and get handled in a 'similar' way.
  CsectGroup UndefinedCsects;
  CsectGroup ProgramCodeCsects;
  CsectGroup ReadOnlyCsects;
  CsectGroup DataCsects;
  CsectGroup FuncDSCsects;
  CsectGroup TOCCsects;
  CsectGroup BSSCsects;
  CsectGroup TDataCsects;
  CsectGroup TBSSCsects;

  // The Predefined sections.
  CsectSectionEntry Text;
  CsectSectionEntry Data;
  CsectSectionEntry BSS;
  CsectSectionEntry TData;
  CsectSectionEntry TBSS;

  // All the XCOFF sections, in the order they will appear in the section header
  // table.
  std::array<CsectSectionEntry *const, 5> Sections{
      {&Text, &Data, &BSS, &TData, &TBSS}};

  std::vector<DwarfSectionEntry> DwarfSections;
  std::vector<SectionEntry> OverflowSections;

  ExceptionSectionEntry ExceptionSection;
  CInfoSymSectionEntry CInfoSymSection;

  CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);

  void reset() override;

  void executePostLayoutBinding(MCAssembler &) override;

  void recordRelocation(MCAssembler &, const MCFragment *, const MCFixup &,
                        MCValue, uint64_t &) override;

  uint64_t writeObject(MCAssembler &) override;

  bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
  bool nameShouldBeInStringTable(const StringRef &);
  void writeSymbolName(const StringRef &);
  bool auxFileSymNameShouldBeInStringTable(const StringRef &);
  void writeAuxFileSymName(const StringRef &);

  void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef,
                                           const XCOFFSection &CSectionRef,
                                           int16_t SectionIndex,
                                           uint64_t SymbolOffset);
  void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef,
                                         int16_t SectionIndex,
                                         XCOFF::StorageClass StorageClass);
  void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef,
                                       int16_t SectionIndex);
  void writeFileHeader();
  void writeAuxFileHeader();
  void writeSectionHeader(const SectionEntry *Sec);
  void writeSectionHeaderTable();
  void writeSections(const MCAssembler &Asm);
  void writeSectionForControlSectionEntry(const MCAssembler &Asm,
                                          const CsectSectionEntry &CsectEntry,
                                          uint64_t &CurrentAddressLocation);
  void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
                                        const DwarfSectionEntry &DwarfEntry,
                                        uint64_t &CurrentAddressLocation);
  void
  writeSectionForExceptionSectionEntry(const MCAssembler &Asm,
                                       ExceptionSectionEntry &ExceptionEntry,
                                       uint64_t &CurrentAddressLocation);
  void writeSectionForCInfoSymSectionEntry(const MCAssembler &Asm,
                                           CInfoSymSectionEntry &CInfoSymEntry,
                                           uint64_t &CurrentAddressLocation);
  void writeSymbolTable(MCAssembler &Asm);
  void writeSymbolAuxFileEntry(StringRef &Name, uint8_t ftype);
  void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
                                uint64_t NumberOfRelocEnt = 0);
  void writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
                                uint8_t SymbolAlignmentAndType,
                                uint8_t StorageMappingClass);
  void writeSymbolAuxFunctionEntry(uint32_t EntryOffset, uint32_t FunctionSize,
                                   uint64_t LineNumberPointer,
                                   uint32_t EndIndex);
  void writeSymbolAuxExceptionEntry(uint64_t EntryOffset, uint32_t FunctionSize,
                                    uint32_t EndIndex);
  void writeSymbolEntry(StringRef SymbolName, uint64_t Value,
                        int16_t SectionNumber, uint16_t SymbolType,
                        uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1);
  void writeRelocations();
  void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);

  // Called after all the csects and symbols have been processed by
  // `executePostLayoutBinding`, this function handles building up the majority
  // of the structures in the object file representation. Namely:
  // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
  //    sizes.
  // *) Assigns symbol table indices.
  // *) Builds up the section header table by adding any non-empty sections to
  //    `Sections`.
  void assignAddressesAndIndices(MCAssembler &Asm);
  // Called after relocations are recorded.
  void finalizeSectionInfo();
  void finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount);
  void calcOffsetToRelocations(SectionEntry *Sec, uint64_t &RawPointer);

  bool hasExceptionSection() {
    return !ExceptionSection.ExceptionTable.empty();
  }
  unsigned getExceptionSectionSize();
  unsigned getExceptionOffset(const MCSymbol *Symbol);

  size_t auxiliaryHeaderSize() const {
    // 64-bit object files have no auxiliary header.
    return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0;
  }

public:
  XCOFFWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
              raw_pwrite_stream &OS);

  void writeWord(uint64_t Word) {
    is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word);
  }

  void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap,
                         unsigned LanguageCode, unsigned ReasonCode,
                         unsigned FunctionSize, bool hasDebug) override;
  void addCInfoSymEntry(StringRef Name, StringRef Metadata) override;
};

XCOFFWriter::XCOFFWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
                         raw_pwrite_stream &OS)
    : W(OS, llvm::endianness::big), TargetObjectWriter(std::move(MOTW)),
      Strings(StringTableBuilder::XCOFF),
      Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
           CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
      Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
           CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
      BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
          CsectGroups{&BSSCsects}),
      TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false,
            CsectGroups{&TDataCsects}),
      TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
           CsectGroups{&TBSSCsects}),
      ExceptionSection(".except", XCOFF::STYP_EXCEPT),
      CInfoSymSection(".info", XCOFF::STYP_INFO) {}

void XCOFFWriter::reset() {
  // Clear the mappings we created.
  SymbolIndexMap.clear();
  SectionMap.clear();

  UndefinedCsects.clear();
  // Reset any sections we have written to, and empty the section header table.
  for (auto *Sec : Sections)
    Sec->reset();
  for (auto &DwarfSec : DwarfSections)
    DwarfSec.reset();
  for (auto &OverflowSec : OverflowSections)
    OverflowSec.reset();
  ExceptionSection.reset();
  CInfoSymSection.reset();

  // Reset states in XCOFFWriter.
  SymbolTableEntryCount = 0;
  SymbolTableOffset = 0;
  SectionCount = 0;
  PaddingsBeforeDwarf = 0;
  Strings.clear();

  MCObjectWriter::reset();
}

CsectGroup &XCOFFWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
  switch (MCSec->getMappingClass()) {
  case XCOFF::XMC_PR:
    assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
           "Only an initialized csect can contain program code.");
    return ProgramCodeCsects;
  case XCOFF::XMC_RO:
    assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
           "Only an initialized csect can contain read only data.");
    return ReadOnlyCsects;
  case XCOFF::XMC_RW:
    if (XCOFF::XTY_CM == MCSec->getCSectType())
      return BSSCsects;

    if (XCOFF::XTY_SD == MCSec->getCSectType())
      return DataCsects;

    report_fatal_error("Unhandled mapping of read-write csect to section.");
  case XCOFF::XMC_DS:
    return FuncDSCsects;
  case XCOFF::XMC_BS:
    assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
           "Mapping invalid csect. CSECT with bss storage class must be "
           "common type.");
    return BSSCsects;
  case XCOFF::XMC_TL:
    assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
           "Mapping invalid csect. CSECT with tdata storage class must be "
           "an initialized csect.");
    return TDataCsects;
  case XCOFF::XMC_UL:
    assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
           "Mapping invalid csect. CSECT with tbss storage class must be "
           "an uninitialized csect.");
    return TBSSCsects;
  case XCOFF::XMC_TC0:
    assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
           "Only an initialized csect can contain TOC-base.");
    assert(TOCCsects.empty() &&
           "We should have only one TOC-base, and it should be the first csect "
           "in this CsectGroup.");
    return TOCCsects;
  case XCOFF::XMC_TC:
  case XCOFF::XMC_TE:
    assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
           "A TOC symbol must be an initialized csect.");
    assert(!TOCCsects.empty() &&
           "We should at least have a TOC-base in this CsectGroup.");
    return TOCCsects;
  case XCOFF::XMC_TD:
    assert((XCOFF::XTY_SD == MCSec->getCSectType() ||
            XCOFF::XTY_CM == MCSec->getCSectType()) &&
           "Symbol type incompatible with toc-data.");
    assert(!TOCCsects.empty() &&
           "We should at least have a TOC-base in this CsectGroup.");
    return TOCCsects;
  default:
    report_fatal_error("Unhandled mapping of csect to section.");
  }
}

static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
  if (XSym->isDefined())
    return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
  return XSym->getRepresentedCsect();
}

void XCOFFWriter::executePostLayoutBinding(MCAssembler &Asm) {
  for (const auto &S : Asm) {
    const auto *MCSec = cast<const MCSectionXCOFF>(&S);
    assert(!SectionMap.contains(MCSec) && "Cannot add a section twice.");

    // If the name does not fit in the storage provided in the symbol table
    // entry, add it to the string table.
    if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
      Strings.add(MCSec->getSymbolTableName());
    if (MCSec->isCsect()) {
      // A new control section. Its CsectSectionEntry should already be staticly
      // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
      // the CsectSectionEntry.
      assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
             "An undefined csect should not get registered.");
      CsectGroup &Group = getCsectGroup(MCSec);
      Group.emplace_back(MCSec);
      SectionMap[MCSec] = &Group.back();
    } else if (MCSec->isDwarfSect()) {
      // A new DwarfSectionEntry.
      std::unique_ptr<XCOFFSection> DwarfSec =
          std::make_unique<XCOFFSection>(MCSec);
      SectionMap[MCSec] = DwarfSec.get();

      DwarfSectionEntry SecEntry(MCSec->getName(),
                                 *MCSec->getDwarfSubtypeFlags(),
                                 std::move(DwarfSec));
      DwarfSections.push_back(std::move(SecEntry));
    } else
      llvm_unreachable("unsupport section type!");
  }

  for (const MCSymbol &S : Asm.symbols()) {
    // Nothing to do for temporary symbols.
    if (S.isTemporary())
      continue;

    const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
    const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);

    if (ContainingCsect->isDwarfSect())
      continue;

    if (XSym->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED)
      HasVisibility = true;

    if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
      // Handle undefined symbol.
      UndefinedCsects.emplace_back(ContainingCsect);
      SectionMap[ContainingCsect] = &UndefinedCsects.back();
      if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
        Strings.add(ContainingCsect->getSymbolTableName());
      continue;
    }

    // If the symbol is the csect itself, we don't need to put the symbol
    // into csect's Syms.
    if (XSym == ContainingCsect->getQualNameSymbol())
      continue;

    // Only put a label into the symbol table when it is an external label.
    if (!XSym->isExternal())
      continue;

    assert(SectionMap.contains(ContainingCsect) &&
           "Expected containing csect to exist in map");
    XCOFFSection *Csect = SectionMap[ContainingCsect];
    // Lookup the containing csect and add the symbol to it.
    assert(Csect->MCSec->isCsect() && "only csect is supported now!");
    Csect->Syms.emplace_back(XSym);

    // If the name does not fit in the storage provided in the symbol table
    // entry, add it to the string table.
    if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
      Strings.add(XSym->getSymbolTableName());
  }

  std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry;
  if (CISI && nameShouldBeInStringTable(CISI->Name))
    Strings.add(CISI->Name);

  // Emit ".file" as the source file name when there is no file name.
  if (FileNames.empty())
    FileNames.emplace_back(".file", 0);
  for (const std::pair<std::string, size_t> &F : FileNames) {
    if (auxFileSymNameShouldBeInStringTable(F.first))
      Strings.add(F.first);
  }

  // Always add ".file" to the symbol table. The actual file name will be in
  // the AUX_FILE auxiliary entry.
  if (nameShouldBeInStringTable(".file"))
    Strings.add(".file");
  StringRef Vers = CompilerVersion;
  if (auxFileSymNameShouldBeInStringTable(Vers))
    Strings.add(Vers);

  Strings.finalize();
  assignAddressesAndIndices(Asm);
}

void XCOFFWriter::recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
                                   const MCFixup &Fixup, MCValue Target,
                                   uint64_t &FixedValue) {
  auto getIndex = [this](const MCSymbol *Sym,
                         const MCSectionXCOFF *ContainingCsect) {
    // If we could not find the symbol directly in SymbolIndexMap, this symbol
    // could either be a temporary symbol or an undefined symbol. In this case,
    // we would need to have the relocation reference its csect instead.
    auto It = SymbolIndexMap.find(Sym);
    return It != SymbolIndexMap.end()
               ? It->second
               : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
  };

  auto getVirtualAddress =
      [this, &Asm](const MCSymbol *Sym,
                   const MCSectionXCOFF *ContainingSect) -> uint64_t {
    // A DWARF section.
    if (ContainingSect->isDwarfSect())
      return Asm.getSymbolOffset(*Sym);

    // A csect.
    if (!Sym->isDefined())
      return SectionMap[ContainingSect]->Address;

    // A label.
    assert(Sym->isDefined() && "not a valid object that has address!");
    return SectionMap[ContainingSect]->Address + Asm.getSymbolOffset(*Sym);
  };

  const MCSymbol *const SymA = &Target.getSymA()->getSymbol();

  MCAsmBackend &Backend = Asm.getBackend();
  bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
                 MCFixupKindInfo::FKF_IsPCRel;

  uint8_t Type;
  uint8_t SignAndSize;
  std::tie(Type, SignAndSize) =
      TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);

  const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
  assert(SectionMap.contains(SymASec) &&
         "Expected containing csect to exist in map.");

  assert((Fixup.getOffset() <=
          MaxRawDataSize - Asm.getFragmentOffset(*Fragment)) &&
         "Fragment offset + fixup offset is overflowed.");
  uint32_t FixupOffsetInCsect =
      Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();

  const uint32_t Index = getIndex(SymA, SymASec);
  if (Type == XCOFF::RelocationType::R_POS ||
      Type == XCOFF::RelocationType::R_TLS ||
      Type == XCOFF::RelocationType::R_TLS_LE ||
      Type == XCOFF::RelocationType::R_TLS_IE ||
      Type == XCOFF::RelocationType::R_TLS_LD)
    // The FixedValue should be symbol's virtual address in this object file
    // plus any constant value that we might get.
    FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
  else if (Type == XCOFF::RelocationType::R_TLSM)
    // The FixedValue should always be zero since the region handle is only
    // known at load time.
    FixedValue = 0;
  else if (Type == XCOFF::RelocationType::R_TOC ||
           Type == XCOFF::RelocationType::R_TOCL) {
    // For non toc-data external symbols, R_TOC type relocation will relocate to
    // data symbols that have XCOFF::XTY_SD type csect. For toc-data external
    // symbols, R_TOC type relocation will relocate to data symbols that have
    // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC
    // entry for them, so the FixedValue should always be 0.
    if (SymASec->getCSectType() == XCOFF::XTY_ER) {
      FixedValue = 0;
    } else {
      // The FixedValue should be the TOC entry offset from the TOC-base plus
      // any constant offset value.
      int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
                               TOCCsects.front().Address + Target.getConstant();
      // For small code model, if the TOCEntryOffset overflows the 16-bit value,
      // we truncate it back down to 16 bits. The linker will be able to insert
      // fix-up code when needed.
      // For non toc-data symbols, we already did the truncation in
      // PPCAsmPrinter.cpp through setting Target.getConstant() in the
      // expression above by calling getTOCEntryLoadingExprForXCOFF for the
      // various TOC PseudoOps.
      // For toc-data symbols, we were not able to calculate the offset from
      // the TOC in PPCAsmPrinter.cpp since the TOC has not been finalized at
      // that point, so we are adjusting it here though
      // llvm::SignExtend64<16>(TOCEntryOffset);
      // TODO: Since the time that the handling for offsets over 16-bits was
      // added in PPCAsmPrinter.cpp using getTOCEntryLoadingExprForXCOFF, the
      // system assembler and linker have been updated to be able to handle the
      // overflowing offsets, so we no longer need to keep
      // getTOCEntryLoadingExprForXCOFF.
      if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
        TOCEntryOffset = llvm::SignExtend64<16>(TOCEntryOffset);

      FixedValue = TOCEntryOffset;
    }
  } else if (Type == XCOFF::RelocationType::R_RBR) {
    MCSectionXCOFF *ParentSec = cast<MCSectionXCOFF>(Fragment->getParent());
    assert((SymASec->getMappingClass() == XCOFF::XMC_PR &&
            ParentSec->getMappingClass() == XCOFF::XMC_PR) &&
           "Only XMC_PR csect may have the R_RBR relocation.");

    // The address of the branch instruction should be the sum of section
    // address, fragment offset and Fixup offset.
    uint64_t BRInstrAddress =
        SectionMap[ParentSec]->Address + FixupOffsetInCsect;
    // The FixedValue should be the difference between symbol's virtual address
    // and BR instr address plus any constant value.
    FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress +
                 Target.getConstant();
  } else if (Type == XCOFF::RelocationType::R_REF) {
    // The FixedValue and FixupOffsetInCsect should always be 0 since it
    // specifies a nonrelocating reference.
    FixedValue = 0;
    FixupOffsetInCsect = 0;
  }

  XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
  MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
  assert(SectionMap.contains(RelocationSec) &&
         "Expected containing csect to exist in map.");
  SectionMap[RelocationSec]->Relocations.push_back(Reloc);

  if (!Target.getSymB())
    return;

  const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
  if (SymA == SymB)
    report_fatal_error("relocation for opposite term is not yet supported");

  const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
  assert(SectionMap.contains(SymBSec) &&
         "Expected containing csect to exist in map.");
  if (SymASec == SymBSec)
    report_fatal_error(
        "relocation for paired relocatable term is not yet supported");

  assert(Type == XCOFF::RelocationType::R_POS &&
         "SymA must be R_POS here if it's not opposite term or paired "
         "relocatable term.");
  const uint32_t IndexB = getIndex(SymB, SymBSec);
  // SymB must be R_NEG here, given the general form of Target(MCValue) is
  // "SymbolA - SymbolB + imm64".
  const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
  XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
  SectionMap[RelocationSec]->Relocations.push_back(RelocB);
  // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
  // now we just need to fold "- SymbolB" here.
  FixedValue -= getVirtualAddress(SymB, SymBSec);
}

void XCOFFWriter::writeSections(const MCAssembler &Asm) {
  uint64_t CurrentAddressLocation = 0;
  for (const auto *Section : Sections)
    writeSectionForControlSectionEntry(Asm, *Section, CurrentAddressLocation);
  for (const auto &DwarfSection : DwarfSections)
    writeSectionForDwarfSectionEntry(Asm, DwarfSection, CurrentAddressLocation);
  writeSectionForExceptionSectionEntry(Asm, ExceptionSection,
                                       CurrentAddressLocation);
  writeSectionForCInfoSymSectionEntry(Asm, CInfoSymSection,
                                      CurrentAddressLocation);
}

uint64_t XCOFFWriter::writeObject(MCAssembler &Asm) {
  // We always emit a timestamp of 0 for reproducibility, so ensure incremental
  // linking is not enabled, in case, like with Windows COFF, such a timestamp
  // is incompatible with incremental linking of XCOFF.

  finalizeSectionInfo();
  uint64_t StartOffset = W.OS.tell();

  writeFileHeader();
  writeAuxFileHeader();
  writeSectionHeaderTable();
  writeSections(Asm);
  writeRelocations();
  writeSymbolTable(Asm);
  // Write the string table.
  Strings.write(W.OS);

  return W.OS.tell() - StartOffset;
}

bool XCOFFWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
  return SymbolName.size() > XCOFF::NameSize || is64Bit();
}

void XCOFFWriter::writeSymbolName(const StringRef &SymbolName) {
  // Magic, Offset or SymbolName.
  if (nameShouldBeInStringTable(SymbolName)) {
    W.write<int32_t>(0);
    W.write<uint32_t>(Strings.getOffset(SymbolName));
  } else {
    char Name[XCOFF::NameSize + 1];
    std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
    ArrayRef<char> NameRef(Name, XCOFF::NameSize);
    W.write(NameRef);
  }
}

void XCOFFWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value,
                                   int16_t SectionNumber, uint16_t SymbolType,
                                   uint8_t StorageClass,
                                   uint8_t NumberOfAuxEntries) {
  if (is64Bit()) {
    W.write<uint64_t>(Value);
    W.write<uint32_t>(Strings.getOffset(SymbolName));
  } else {
    writeSymbolName(SymbolName);
    W.write<uint32_t>(Value);
  }
  W.write<int16_t>(SectionNumber);
  W.write<uint16_t>(SymbolType);
  W.write<uint8_t>(StorageClass);
  W.write<uint8_t>(NumberOfAuxEntries);
}

void XCOFFWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
                                           uint8_t SymbolAlignmentAndType,
                                           uint8_t StorageMappingClass) {
  W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength);
  W.write<uint32_t>(0); // ParameterHashIndex
  W.write<uint16_t>(0); // TypeChkSectNum
  W.write<uint8_t>(SymbolAlignmentAndType);
  W.write<uint8_t>(StorageMappingClass);
  if (is64Bit()) {
    W.write<uint32_t>(Hi_32(SectionOrLength));
    W.OS.write_zeros(1); // Reserved
    W.write<uint8_t>(XCOFF::AUX_CSECT);
  } else {
    W.write<uint32_t>(0); // StabInfoIndex
    W.write<uint16_t>(0); // StabSectNum
  }
}

bool XCOFFWriter::auxFileSymNameShouldBeInStringTable(
    const StringRef &SymbolName) {
  return SymbolName.size() > XCOFF::AuxFileEntNameSize;
}

void XCOFFWriter::writeAuxFileSymName(const StringRef &SymbolName) {
  // Magic, Offset or SymbolName.
  if (auxFileSymNameShouldBeInStringTable(SymbolName)) {
    W.write<int32_t>(0);
    W.write<uint32_t>(Strings.getOffset(SymbolName));
    W.OS.write_zeros(XCOFF::FileNamePadSize);
  } else {
    char Name[XCOFF::AuxFileEntNameSize + 1];
    std::strncpy(Name, SymbolName.data(), XCOFF::AuxFileEntNameSize);
    ArrayRef<char> NameRef(Name, XCOFF::AuxFileEntNameSize);
    W.write(NameRef);
  }
}

void XCOFFWriter::writeSymbolAuxFileEntry(StringRef &Name, uint8_t ftype) {
  writeAuxFileSymName(Name);
  W.write<uint8_t>(ftype);
  W.OS.write_zeros(2);
  if (is64Bit())
    W.write<uint8_t>(XCOFF::AUX_FILE);
  else
    W.OS.write_zeros(1);
}

void XCOFFWriter::writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
                                           uint64_t NumberOfRelocEnt) {
  writeWord(LengthOfSectionPortion);
  if (!is64Bit())
    W.OS.write_zeros(4); // Reserved
  writeWord(NumberOfRelocEnt);
  if (is64Bit()) {
    W.OS.write_zeros(1); // Reserved
    W.write<uint8_t>(XCOFF::AUX_SECT);
  } else {
    W.OS.write_zeros(6); // Reserved
  }
}

void XCOFFWriter::writeSymbolEntryForCsectMemberLabel(
    const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
    int16_t SectionIndex, uint64_t SymbolOffset) {
  assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
         "Symbol address overflowed.");

  auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName());
  if (Entry != ExceptionSection.ExceptionTable.end()) {
    writeSymbolEntry(SymbolRef.getSymbolTableName(),
                     CSectionRef.Address + SymbolOffset, SectionIndex,
                     // In the old version of the 32-bit XCOFF interpretation,
                     // symbols may require bit 10 (0x0020) to be set if the
                     // symbol is a function, otherwise the bit should be 0.
                     is64Bit() ? SymbolRef.getVisibilityType()
                               : SymbolRef.getVisibilityType() | 0x0020,
                     SymbolRef.getStorageClass(),
                     (is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2);
    if (is64Bit() && ExceptionSection.isDebugEnabled) {
      // On 64 bit with debugging enabled, we have a csect, exception, and
      // function auxilliary entries, so we must increment symbol index by 4.
      writeSymbolAuxExceptionEntry(
          ExceptionSection.FileOffsetToData +
              getExceptionOffset(Entry->second.FunctionSymbol),
          Entry->second.FunctionSize,
          SymbolIndexMap[Entry->second.FunctionSymbol] + 4);
    }
    // For exception section entries, csect and function auxilliary entries
    // must exist. On 64-bit there is also an exception auxilliary entry.
    writeSymbolAuxFunctionEntry(
        ExceptionSection.FileOffsetToData +
            getExceptionOffset(Entry->second.FunctionSymbol),
        Entry->second.FunctionSize, 0,
        (is64Bit() && ExceptionSection.isDebugEnabled)
            ? SymbolIndexMap[Entry->second.FunctionSymbol] + 4
            : SymbolIndexMap[Entry->second.FunctionSymbol] + 3);
  } else {
    writeSymbolEntry(SymbolRef.getSymbolTableName(),
                     CSectionRef.Address + SymbolOffset, SectionIndex,
                     SymbolRef.getVisibilityType(),
                     SymbolRef.getStorageClass());
  }
  writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD,
                           CSectionRef.MCSec->getMappingClass());
}

void XCOFFWriter::writeSymbolEntryForDwarfSection(
    const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
  assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");

  writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0,
                   SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF);

  writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
}

void XCOFFWriter::writeSymbolEntryForControlSection(
    const XCOFFSection &CSectionRef, int16_t SectionIndex,
    XCOFF::StorageClass StorageClass) {
  writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
                   SectionIndex, CSectionRef.getVisibilityType(), StorageClass);

  writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
                           CSectionRef.MCSec->getMappingClass());
}

void XCOFFWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset,
                                              uint32_t FunctionSize,
                                              uint64_t LineNumberPointer,
                                              uint32_t EndIndex) {
  if (is64Bit())
    writeWord(LineNumberPointer);
  else
    W.write<uint32_t>(EntryOffset);
  W.write<uint32_t>(FunctionSize);
  if (!is64Bit())
    writeWord(LineNumberPointer);
  W.write<uint32_t>(EndIndex);
  if (is64Bit()) {
    W.OS.write_zeros(1);
    W.write<uint8_t>(XCOFF::AUX_FCN);
  } else {
    W.OS.write_zeros(2);
  }
}

void XCOFFWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset,
                                               uint32_t FunctionSize,
                                               uint32_t EndIndex) {
  assert(is64Bit() && "Exception auxilliary entries are 64-bit only.");
  W.write<uint64_t>(EntryOffset);
  W.write<uint32_t>(FunctionSize);
  W.write<uint32_t>(EndIndex);
  W.OS.write_zeros(1); // Pad (unused)
  W.write<uint8_t>(XCOFF::AUX_EXCEPT);
}

void XCOFFWriter::writeFileHeader() {
  W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32);
  W.write<uint16_t>(SectionCount);
  W.write<int32_t>(0); // TimeStamp
  writeWord(SymbolTableOffset);
  if (is64Bit()) {
    W.write<uint16_t>(auxiliaryHeaderSize());
    W.write<uint16_t>(0); // Flags
    W.write<int32_t>(SymbolTableEntryCount);
  } else {
    W.write<int32_t>(SymbolTableEntryCount);
    W.write<uint16_t>(auxiliaryHeaderSize());
    W.write<uint16_t>(0); // Flags
  }
}

void XCOFFWriter::writeAuxFileHeader() {
  if (!auxiliaryHeaderSize())
    return;
  W.write<uint16_t>(0); // Magic
  W.write<uint16_t>(
      XCOFF::NEW_XCOFF_INTERPRET); // Version. The new interpretation of the
                                   // n_type field in the symbol table entry is
                                   // used in XCOFF32.
  W.write<uint32_t>(Sections[0]->Size);    // TextSize
  W.write<uint32_t>(Sections[1]->Size);    // InitDataSize
  W.write<uint32_t>(Sections[2]->Size);    // BssDataSize
  W.write<uint32_t>(0);                    // EntryPointAddr
  W.write<uint32_t>(Sections[0]->Address); // TextStartAddr
  W.write<uint32_t>(Sections[1]->Address); // DataStartAddr
}

void XCOFFWriter::writeSectionHeader(const SectionEntry *Sec) {
  bool IsDwarf = (Sec->Flags & XCOFF::STYP_DWARF) != 0;
  bool IsOvrflo = (Sec->Flags & XCOFF::STYP_OVRFLO) != 0;
  // Nothing to write for this Section.
  if (Sec->Index == SectionEntry::UninitializedIndex)
    return;

  // Write Name.
  ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
  W.write(NameRef);

  // Write the Physical Address and Virtual Address.
  // We use 0 for DWARF sections' Physical and Virtual Addresses.
  writeWord(IsDwarf ? 0 : Sec->Address);
  // Since line number is not supported, we set it to 0 for overflow sections.
  writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address);

  writeWord(Sec->Size);
  writeWord(Sec->FileOffsetToData);
  writeWord(Sec->FileOffsetToRelocations);
  writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.

  if (is64Bit()) {
    W.write<uint32_t>(Sec->RelocationCount);
    W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
    W.write<int32_t>(Sec->Flags);
    W.OS.write_zeros(4);
  } else {
    // For the overflow section header, s_nreloc provides a reference to the
    // primary section header and s_nlnno must have the same value.
    // For common section headers, if either of s_nreloc or s_nlnno are set to
    // 65535, the other one must also be set to 65535.
    W.write<uint16_t>(Sec->RelocationCount);
    W.write<uint16_t>((IsOvrflo || Sec->RelocationCount == XCOFF::RelocOverflow)
                          ? Sec->RelocationCount
                          : 0); // NumberOfLineNumbers. Not supported yet.
    W.write<int32_t>(Sec->Flags);
  }
}

void XCOFFWriter::writeSectionHeaderTable() {
  for (const auto *CsectSec : Sections)
    writeSectionHeader(CsectSec);
  for (const auto &DwarfSec : DwarfSections)
    writeSectionHeader(&DwarfSec);
  for (const auto &OverflowSec : OverflowSections)
    writeSectionHeader(&OverflowSec);
  if (hasExceptionSection())
    writeSectionHeader(&ExceptionSection);
  if (CInfoSymSection.Entry)
    writeSectionHeader(&CInfoSymSection);
}

void XCOFFWriter::writeRelocation(XCOFFRelocation Reloc,
                                  const XCOFFSection &Section) {
  if (Section.MCSec->isCsect())
    writeWord(Section.Address + Reloc.FixupOffsetInCsect);
  else {
    // DWARF sections' address is set to 0.
    assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
    writeWord(Reloc.FixupOffsetInCsect);
  }
  W.write<uint32_t>(Reloc.SymbolTableIndex);
  W.write<uint8_t>(Reloc.SignAndSize);
  W.write<uint8_t>(Reloc.Type);
}

void XCOFFWriter::writeRelocations() {
  for (const auto *Section : Sections) {
    if (Section->Index == SectionEntry::UninitializedIndex)
      // Nothing to write for this Section.
      continue;

    for (const auto *Group : Section->Groups) {
      if (Group->empty())
        continue;

      for (const auto &Csect : *Group) {
        for (const auto Reloc : Csect.Relocations)
          writeRelocation(Reloc, Csect);
      }
    }
  }

  for (const auto &DwarfSection : DwarfSections)
    for (const auto &Reloc : DwarfSection.DwarfSect->Relocations)
      writeRelocation(Reloc, *DwarfSection.DwarfSect);
}

void XCOFFWriter::writeSymbolTable(MCAssembler &Asm) {
  // Write C_FILE symbols.
  StringRef Vers = CompilerVersion;

  for (const std::pair<std::string, size_t> &F : FileNames) {
    // The n_name of a C_FILE symbol is the source file's name when no auxiliary
    // entries are present.
    StringRef FileName = F.first;

    // For C_FILE symbols, the Source Language ID overlays the high-order byte
    // of the SymbolType field, and the CPU Version ID is defined as the
    // low-order byte.
    // AIX's system assembler determines the source language ID based on the
    // source file's name suffix, and the behavior here is consistent with it.
    uint8_t LangID;
    if (FileName.ends_with(".c"))
      LangID = XCOFF::TB_C;
    else if (FileName.ends_with_insensitive(".f") ||
             FileName.ends_with_insensitive(".f77") ||
             FileName.ends_with_insensitive(".f90") ||
             FileName.ends_with_insensitive(".f95") ||
             FileName.ends_with_insensitive(".f03") ||
             FileName.ends_with_insensitive(".f08"))
      LangID = XCOFF::TB_Fortran;
    else
      LangID = XCOFF::TB_CPLUSPLUS;

    uint8_t CpuID = XCOFF::getCpuID(getCPUType());

    int NumberOfFileAuxEntries = 1;
    if (!Vers.empty())
      ++NumberOfFileAuxEntries;
    writeSymbolEntry(".file", /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG,
                     /*SymbolType=*/(LangID << 8) | CpuID, XCOFF::C_FILE,
                     NumberOfFileAuxEntries);
    writeSymbolAuxFileEntry(FileName, XCOFF::XFT_FN);
    if (!Vers.empty())
      writeSymbolAuxFileEntry(Vers, XCOFF::XFT_CV);
  }

  if (CInfoSymSection.Entry)
    writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset,
                     CInfoSymSection.Index,
                     /*SymbolType=*/0, XCOFF::C_INFO,
                     /*NumberOfAuxEntries=*/0);

  for (const auto &Csect : UndefinedCsects) {
    writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
                                      Csect.MCSec->getStorageClass());
  }

  for (const auto *Section : Sections) {
    if (Section->Index == SectionEntry::UninitializedIndex)
      // Nothing to write for this Section.
      continue;

    for (const auto *Group : Section->Groups) {
      if (Group->empty())
        continue;

      const int16_t SectionIndex = Section->Index;
      for (const auto &Csect : *Group) {
        // Write out the control section first and then each symbol in it.
        writeSymbolEntryForControlSection(Csect, SectionIndex,
                                          Csect.MCSec->getStorageClass());

        for (const auto &Sym : Csect.Syms)
          writeSymbolEntryForCsectMemberLabel(
              Sym, Csect, SectionIndex, Asm.getSymbolOffset(*(Sym.MCSym)));
      }
    }
  }

  for (const auto &DwarfSection : DwarfSections)
    writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
                                    DwarfSection.Index);
}

void XCOFFWriter::finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount) {
  // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file
  // may not contain an overflow section header.
  if (!is64Bit() && (RelCount >= static_cast<uint32_t>(XCOFF::RelocOverflow))) {
    // Generate an overflow section header.
    SectionEntry SecEntry(".ovrflo", XCOFF::STYP_OVRFLO);

    // This field specifies the file section number of the section header that
    // overflowed.
    SecEntry.RelocationCount = Sec->Index;

    // This field specifies the number of relocation entries actually
    // required.
    SecEntry.Address = RelCount;
    SecEntry.Index = ++SectionCount;
    OverflowSections.push_back(std::move(SecEntry));

    // The field in the primary section header is always 65535
    // (XCOFF::RelocOverflow).
    Sec->RelocationCount = XCOFF::RelocOverflow;
  } else {
    Sec->RelocationCount = RelCount;
  }
}

void XCOFFWriter::calcOffsetToRelocations(SectionEntry *Sec,
                                          uint64_t &RawPointer) {
  if (!Sec->RelocationCount)
    return;

  Sec->FileOffsetToRelocations = RawPointer;
  uint64_t RelocationSizeInSec = 0;
  if (!is64Bit() &&
      Sec->RelocationCount == static_cast<uint32_t>(XCOFF::RelocOverflow)) {
    // Find its corresponding overflow section.
    for (auto &OverflowSec : OverflowSections) {
      if (OverflowSec.RelocationCount == static_cast<uint32_t>(Sec->Index)) {
        RelocationSizeInSec =
            OverflowSec.Address * XCOFF::RelocationSerializationSize32;

        // This field must have the same values as in the corresponding
        // primary section header.
        OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations;
      }
    }
    assert(RelocationSizeInSec && "Overflow section header doesn't exist.");
  } else {
    RelocationSizeInSec = Sec->RelocationCount *
                          (is64Bit() ? XCOFF::RelocationSerializationSize64
                                     : XCOFF::RelocationSerializationSize32);
  }

  RawPointer += RelocationSizeInSec;
  if (RawPointer > MaxRawDataSize)
    report_fatal_error("Relocation data overflowed this object file.");
}

void XCOFFWriter::finalizeSectionInfo() {
  for (auto *Section : Sections) {
    if (Section->Index == SectionEntry::UninitializedIndex)
      // Nothing to record for this Section.
      continue;

    uint64_t RelCount = 0;
    for (const auto *Group : Section->Groups) {
      if (Group->empty())
        continue;

      for (auto &Csect : *Group)
        RelCount += Csect.Relocations.size();
    }
    finalizeRelocationInfo(Section, RelCount);
  }

  for (auto &DwarfSection : DwarfSections)
    finalizeRelocationInfo(&DwarfSection,
                           DwarfSection.DwarfSect->Relocations.size());

  // Calculate the RawPointer value for all headers.
  uint64_t RawPointer =
      (is64Bit() ? (XCOFF::FileHeaderSize64 +
                    SectionCount * XCOFF::SectionHeaderSize64)
                 : (XCOFF::FileHeaderSize32 +
                    SectionCount * XCOFF::SectionHeaderSize32)) +
      auxiliaryHeaderSize();

  // Calculate the file offset to the section data.
  for (auto *Sec : Sections) {
    if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
      continue;

    RawPointer = Sec->advanceFileOffset(MaxRawDataSize, RawPointer);
  }

  if (!DwarfSections.empty()) {
    RawPointer += PaddingsBeforeDwarf;
    for (auto &DwarfSection : DwarfSections) {
      RawPointer = DwarfSection.advanceFileOffset(MaxRawDataSize, RawPointer);
    }
  }

  if (hasExceptionSection())
    RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer);

  if (CInfoSymSection.Entry)
    RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer);

  for (auto *Sec : Sections) {
    if (Sec->Index != SectionEntry::UninitializedIndex)
      calcOffsetToRelocations(Sec, RawPointer);
  }

  for (auto &DwarfSec : DwarfSections)
    calcOffsetToRelocations(&DwarfSec, RawPointer);

  // TODO Error check that the number of symbol table entries fits in 32-bits
  // signed ...
  if (SymbolTableEntryCount)
    SymbolTableOffset = RawPointer;
}

void XCOFFWriter::addExceptionEntry(const MCSymbol *Symbol,
                                    const MCSymbol *Trap, unsigned LanguageCode,
                                    unsigned ReasonCode, unsigned FunctionSize,
                                    bool hasDebug) {
  // If a module had debug info, debugging is enabled and XCOFF emits the
  // exception auxilliary entry.
  if (hasDebug)
    ExceptionSection.isDebugEnabled = true;
  auto Entry = ExceptionSection.ExceptionTable.find(Symbol->getName());
  if (Entry != ExceptionSection.ExceptionTable.end()) {
    Entry->second.Entries.push_back(
        ExceptionTableEntry(Trap, LanguageCode, ReasonCode));
    return;
  }
  ExceptionInfo NewEntry;
  NewEntry.FunctionSymbol = Symbol;
  NewEntry.FunctionSize = FunctionSize;
  NewEntry.Entries.push_back(
      ExceptionTableEntry(Trap, LanguageCode, ReasonCode));
  ExceptionSection.ExceptionTable.insert(
      std::pair<const StringRef, ExceptionInfo>(Symbol->getName(), NewEntry));
}

unsigned XCOFFWriter::getExceptionSectionSize() {
  unsigned EntryNum = 0;

  for (const auto &TableEntry : ExceptionSection.ExceptionTable)
    // The size() gets +1 to account for the initial entry containing the
    // symbol table index.
    EntryNum += TableEntry.second.Entries.size() + 1;

  return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
                               : XCOFF::ExceptionSectionEntrySize32);
}

unsigned XCOFFWriter::getExceptionOffset(const MCSymbol *Symbol) {
  unsigned EntryNum = 0;
  for (const auto &TableEntry : ExceptionSection.ExceptionTable) {
    if (Symbol == TableEntry.second.FunctionSymbol)
      break;
    EntryNum += TableEntry.second.Entries.size() + 1;
  }
  return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
                               : XCOFF::ExceptionSectionEntrySize32);
}

void XCOFFWriter::addCInfoSymEntry(StringRef Name, StringRef Metadata) {
  assert(!CInfoSymSection.Entry && "Multiple entries are not supported");
  CInfoSymSection.addEntry(
      std::make_unique<CInfoSymInfo>(Name.str(), Metadata.str()));
}

void XCOFFWriter::assignAddressesAndIndices(MCAssembler &Asm) {
  // The symbol table starts with all the C_FILE symbols. Each C_FILE symbol
  // requires 1 or 2 auxiliary entries.
  uint32_t SymbolTableIndex =
      (2 + (CompilerVersion.empty() ? 0 : 1)) * FileNames.size();

  if (CInfoSymSection.Entry)
    SymbolTableIndex++;

  // Calculate indices for undefined symbols.
  for (auto &Csect : UndefinedCsects) {
    Csect.Size = 0;
    Csect.Address = 0;
    Csect.SymbolTableIndex = SymbolTableIndex;
    SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
    // 1 main and 1 auxiliary symbol table entry for each contained symbol.
    SymbolTableIndex += 2;
  }

  // The address corrresponds to the address of sections and symbols in the
  // object file. We place the shared address 0 immediately after the
  // section header table.
  uint64_t Address = 0;
  // Section indices are 1-based in XCOFF.
  int32_t SectionIndex = 1;
  bool HasTDataSection = false;

  for (auto *Section : Sections) {
    const bool IsEmpty =
        llvm::all_of(Section->Groups,
                     [](const CsectGroup *Group) { return Group->empty(); });
    if (IsEmpty)
      continue;

    if (SectionIndex > MaxSectionIndex)
      report_fatal_error("Section index overflow!");
    Section->Index = SectionIndex++;
    SectionCount++;

    bool SectionAddressSet = false;
    // Reset the starting address to 0 for TData section.
    if (Section->Flags == XCOFF::STYP_TDATA) {
      Address = 0;
      HasTDataSection = true;
    }
    // Reset the starting address to 0 for TBSS section if the object file does
    // not contain TData Section.
    if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection)
      Address = 0;

    for (auto *Group : Section->Groups) {
      if (Group->empty())
        continue;

      for (auto &Csect : *Group) {
        const MCSectionXCOFF *MCSec = Csect.MCSec;
        Csect.Address = alignTo(Address, MCSec->getAlign());
        Csect.Size = Asm.getSectionAddressSize(*MCSec);
        Address = Csect.Address + Csect.Size;
        Csect.SymbolTableIndex = SymbolTableIndex;
        SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
        // 1 main and 1 auxiliary symbol table entry for the csect.
        SymbolTableIndex += 2;

        for (auto &Sym : Csect.Syms) {
          bool hasExceptEntry = false;
          auto Entry =
              ExceptionSection.ExceptionTable.find(Sym.MCSym->getName());
          if (Entry != ExceptionSection.ExceptionTable.end()) {
            hasExceptEntry = true;
            for (auto &TrapEntry : Entry->second.Entries) {
              TrapEntry.TrapAddress = Asm.getSymbolOffset(*(Sym.MCSym)) +
                                      TrapEntry.Trap->getOffset();
            }
          }
          Sym.SymbolTableIndex = SymbolTableIndex;
          SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
          // 1 main and 1 auxiliary symbol table entry for each contained
          // symbol. For symbols with exception section entries, a function
          // auxilliary entry is needed, and on 64-bit XCOFF with debugging
          // enabled, an additional exception auxilliary entry is needed.
          SymbolTableIndex += 2;
          if (hasExceptionSection() && hasExceptEntry) {
            if (is64Bit() && ExceptionSection.isDebugEnabled)
              SymbolTableIndex += 2;
            else
              SymbolTableIndex += 1;
          }
        }
      }

      if (!SectionAddressSet) {
        Section->Address = Group->front().Address;
        SectionAddressSet = true;
      }
    }

    // Make sure the address of the next section aligned to
    // DefaultSectionAlign.
    Address = alignTo(Address, DefaultSectionAlign);
    Section->Size = Address - Section->Address;
  }

  // Start to generate DWARF sections. Sections other than DWARF section use
  // DefaultSectionAlign as the default alignment, while DWARF sections have
  // their own alignments. If these two alignments are not the same, we need
  // some paddings here and record the paddings bytes for FileOffsetToData
  // calculation.
  if (!DwarfSections.empty())
    PaddingsBeforeDwarf =
        alignTo(Address,
                (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) -
        Address;

  DwarfSectionEntry *LastDwarfSection = nullptr;
  for (auto &DwarfSection : DwarfSections) {
    assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");

    XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
    const MCSectionXCOFF *MCSec = DwarfSect.MCSec;

    // Section index.
    DwarfSection.Index = SectionIndex++;
    SectionCount++;

    // Symbol index.
    DwarfSect.SymbolTableIndex = SymbolTableIndex;
    SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex;
    // 1 main and 1 auxiliary symbol table entry for the csect.
    SymbolTableIndex += 2;

    // Section address. Make it align to section alignment.
    // We use address 0 for DWARF sections' Physical and Virtual Addresses.
    // This address is used to tell where is the section in the final object.
    // See writeSectionForDwarfSectionEntry().
    DwarfSection.Address = DwarfSect.Address =
        alignTo(Address, MCSec->getAlign());

    // Section size.
    // For DWARF section, we must use the real size which may be not aligned.
    DwarfSection.Size = DwarfSect.Size = Asm.getSectionAddressSize(*MCSec);

    Address = DwarfSection.Address + DwarfSection.Size;

    if (LastDwarfSection)
      LastDwarfSection->MemorySize =
          DwarfSection.Address - LastDwarfSection->Address;
    LastDwarfSection = &DwarfSection;
  }
  if (LastDwarfSection) {
    // Make the final DWARF section address align to the default section
    // alignment for follow contents.
    Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size,
                      DefaultSectionAlign);
    LastDwarfSection->MemorySize = Address - LastDwarfSection->Address;
  }
  if (hasExceptionSection()) {
    ExceptionSection.Index = SectionIndex++;
    SectionCount++;
    ExceptionSection.Address = 0;
    ExceptionSection.Size = getExceptionSectionSize();
    Address += ExceptionSection.Size;
    Address = alignTo(Address, DefaultSectionAlign);
  }

  if (CInfoSymSection.Entry) {
    CInfoSymSection.Index = SectionIndex++;
    SectionCount++;
    CInfoSymSection.Address = 0;
    Address += CInfoSymSection.Size;
    Address = alignTo(Address, DefaultSectionAlign);
  }

  SymbolTableEntryCount = SymbolTableIndex;
}

void XCOFFWriter::writeSectionForControlSectionEntry(
    const MCAssembler &Asm, const CsectSectionEntry &CsectEntry,
    uint64_t &CurrentAddressLocation) {
  // Nothing to write for this Section.
  if (CsectEntry.Index == SectionEntry::UninitializedIndex)
    return;

  // There could be a gap (without corresponding zero padding) between
  // sections.
  // There could be a gap (without corresponding zero padding) between
  // sections.
  assert(((CurrentAddressLocation <= CsectEntry.Address) ||
          (CsectEntry.Flags == XCOFF::STYP_TDATA) ||
          (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&
         "CurrentAddressLocation should be less than or equal to section "
         "address if the section is not TData or TBSS.");

  CurrentAddressLocation = CsectEntry.Address;

  // For virtual sections, nothing to write. But need to increase
  // CurrentAddressLocation for later sections like DWARF section has a correct
  // writing location.
  if (CsectEntry.IsVirtual) {
    CurrentAddressLocation += CsectEntry.Size;
    return;
  }

  for (const auto &Group : CsectEntry.Groups) {
    for (const auto &Csect : *Group) {
      if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
        W.OS.write_zeros(PaddingSize);
      if (Csect.Size)
        Asm.writeSectionData(W.OS, Csect.MCSec);
      CurrentAddressLocation = Csect.Address + Csect.Size;
    }
  }

  // The size of the tail padding in a section is the end virtual address of
  // the current section minus the end virtual address of the last csect
  // in that section.
  if (uint64_t PaddingSize =
          CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
    W.OS.write_zeros(PaddingSize);
    CurrentAddressLocation += PaddingSize;
  }
}

void XCOFFWriter::writeSectionForDwarfSectionEntry(
    const MCAssembler &Asm, const DwarfSectionEntry &DwarfEntry,
    uint64_t &CurrentAddressLocation) {
  // There could be a gap (without corresponding zero padding) between
  // sections. For example DWARF section alignment is bigger than
  // DefaultSectionAlign.
  assert(CurrentAddressLocation <= DwarfEntry.Address &&
         "CurrentAddressLocation should be less than or equal to section "
         "address.");

  if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
    W.OS.write_zeros(PaddingSize);

  if (DwarfEntry.Size)
    Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec);

  CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;

  // DWARF section size is not aligned to DefaultSectionAlign.
  // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
  uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
  uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0;
  if (TailPaddingSize)
    W.OS.write_zeros(TailPaddingSize);

  CurrentAddressLocation += TailPaddingSize;
}

void XCOFFWriter::writeSectionForExceptionSectionEntry(
    const MCAssembler &Asm, ExceptionSectionEntry &ExceptionEntry,
    uint64_t &CurrentAddressLocation) {
  for (const auto &TableEntry : ExceptionEntry.ExceptionTable) {
    // For every symbol that has exception entries, you must start the entries
    // with an initial symbol table index entry
    W.write<uint32_t>(SymbolIndexMap[TableEntry.second.FunctionSymbol]);
    if (is64Bit()) {
      // 4-byte padding on 64-bit.
      W.OS.write_zeros(4);
    }
    W.OS.write_zeros(2);
    for (auto &TrapEntry : TableEntry.second.Entries) {
      writeWord(TrapEntry.TrapAddress);
      W.write<uint8_t>(TrapEntry.Lang);
      W.write<uint8_t>(TrapEntry.Reason);
    }
  }

  CurrentAddressLocation += getExceptionSectionSize();
}

void XCOFFWriter::writeSectionForCInfoSymSectionEntry(
    const MCAssembler &Asm, CInfoSymSectionEntry &CInfoSymEntry,
    uint64_t &CurrentAddressLocation) {
  if (!CInfoSymSection.Entry)
    return;

  constexpr int WordSize = sizeof(uint32_t);
  std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry;
  const std::string &Metadata = CISI->Metadata;

  // Emit the 4-byte length of the metadata.
  W.write<uint32_t>(Metadata.size());

  if (Metadata.size() == 0)
    return;

  // Write out the payload one word at a time.
  size_t Index = 0;
  while (Index + WordSize <= Metadata.size()) {
    uint32_t NextWord =
        llvm::support::endian::read32be(Metadata.data() + Index);
    W.write<uint32_t>(NextWord);
    Index += WordSize;
  }

  // If there is padding, we have at least one byte of payload left to emit.
  if (CISI->paddingSize()) {
    std::array<uint8_t, WordSize> LastWord = {0};
    ::memcpy(LastWord.data(), Metadata.data() + Index, Metadata.size() - Index);
    W.write<uint32_t>(llvm::support::endian::read32be(LastWord.data()));
  }

  CurrentAddressLocation += CISI->size();
}

// Takes the log base 2 of the alignment and shifts the result into the 5 most
// significant bits of a byte, then or's in the csect type into the least
// significant 3 bits.
uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
  unsigned Log2Align = Log2(Sec->getAlign());
  // Result is a number in the range [0, 31] which fits in the 5 least
  // significant bits. Shift this value into the 5 most significant bits, and
  // bitwise-or in the csect type.
  uint8_t EncodedAlign = Log2Align << 3;
  return EncodedAlign | Sec->getCSectType();
}

} // end anonymous namespace

std::unique_ptr<MCObjectWriter>
llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
                              raw_pwrite_stream &OS) {
  return std::make_unique<XCOFFWriter>(std::move(MOTW), OS);
}
