//===-- 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/MCAsmLayout.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 XCOFFObjectWriter : public MCObjectWriter {

  uint32_t SymbolTableEntryCount = 0;
  uint64_t SymbolTableOffset = 0;
  uint16_t SectionCount = 0;
  uint32_t PaddingsBeforeDwarf = 0;
  std::vector<std::pair<std::string, size_t>> FileNames;
  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 &, const MCAsmLayout &) override;

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

  uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;

  bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
  bool nameShouldBeInStringTable(const StringRef &);
  void writeSymbolName(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, const MCAsmLayout &Layout);
  void writeSectionForControlSectionEntry(const MCAssembler &Asm,
                                          const MCAsmLayout &Layout,
                                          const CsectSectionEntry &CsectEntry,
                                          uint64_t &CurrentAddressLocation);
  void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
                                        const MCAsmLayout &Layout,
                                        const DwarfSectionEntry &DwarfEntry,
                                        uint64_t &CurrentAddressLocation);
  void writeSectionForExceptionSectionEntry(
      const MCAssembler &Asm, const MCAsmLayout &Layout,
      ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation);
  void writeSectionForCInfoSymSectionEntry(const MCAssembler &Asm,
                                           const MCAsmLayout &Layout,
                                           CInfoSymSectionEntry &CInfoSymEntry,
                                           uint64_t &CurrentAddressLocation);
  void writeSymbolTable(const MCAsmLayout &Layout);
  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(const MCAsmLayout &);
  // Called after relocations are recorded.
  void finalizeSectionInfo();
  void finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount);
  void calcOffsetToRelocations(SectionEntry *Sec, uint64_t &RawPointer);

  void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap,
                         unsigned LanguageCode, unsigned ReasonCode,
                         unsigned FunctionSize, bool hasDebug) override;
  bool hasExceptionSection() {
    return !ExceptionSection.ExceptionTable.empty();
  }
  unsigned getExceptionSectionSize();
  unsigned getExceptionOffset(const MCSymbol *Symbol);

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

public:
  XCOFFObjectWriter(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);
  }
};

XCOFFObjectWriter::XCOFFObjectWriter(
    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 XCOFFObjectWriter::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 XCOFFObjectWriter.
  SymbolTableEntryCount = 0;
  SymbolTableOffset = 0;
  SectionCount = 0;
  PaddingsBeforeDwarf = 0;
  Strings.clear();

  MCObjectWriter::reset();
}

CsectGroup &XCOFFObjectWriter::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:
  case XCOFF::XMC_TD:
    assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
           "Only an initialized csect can contain TC entry.");
    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 XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
                                                 const MCAsmLayout &Layout) {
  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 (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);

  FileNames = Asm.getFileNames();
  // 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 (nameShouldBeInStringTable(F.first))
      Strings.add(F.first);
  }

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

void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
                                         const MCAsmLayout &Layout,
                                         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.
    return SymbolIndexMap.contains(Sym)
               ? SymbolIndexMap[Sym]
               : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
  };

  auto getVirtualAddress =
      [this, &Layout](const MCSymbol *Sym,
                      const MCSectionXCOFF *ContainingSect) -> uint64_t {
    // A DWARF section.
    if (ContainingSect->isDwarfSect())
      return Layout.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 + Layout.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 - Layout.getFragmentOffset(Fragment)) &&
         "Fragment offset + fixup offset is overflowed.");
  uint32_t FixupOffsetInCsect =
      Layout.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)
    // 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.
      const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
                                     TOCCsects.front().Address +
                                     Target.getConstant();
      if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
        report_fatal_error("TOCEntryOffset overflows in small code model mode");

      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 XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
                                      const MCAsmLayout &Layout) {
  uint64_t CurrentAddressLocation = 0;
  for (const auto *Section : Sections)
    writeSectionForControlSectionEntry(Asm, Layout, *Section,
                                       CurrentAddressLocation);
  for (const auto &DwarfSection : DwarfSections)
    writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection,
                                     CurrentAddressLocation);
  writeSectionForExceptionSectionEntry(Asm, Layout, ExceptionSection,
                                       CurrentAddressLocation);
  writeSectionForCInfoSymSectionEntry(Asm, Layout, CInfoSymSection,
                                      CurrentAddressLocation);
}

uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
                                        const MCAsmLayout &Layout) {
  // 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.
  if (Asm.isIncrementalLinkerCompatible())
    report_fatal_error("Incremental linking not supported for XCOFF.");

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

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

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

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

void XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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
  }
}

void XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
  // Write C_FILE symbols.
  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;
    if (is64Bit())
      CpuID = XCOFF::TCPU_PPC64;
    else
      CpuID = XCOFF::TCPU_COM;

    writeSymbolEntry(FileName, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG,
                     /*SymbolType=*/(LangID << 8) | CpuID, XCOFF::C_FILE,
                     /*NumberOfAuxEntries=*/0);
  }

  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, Layout.getSymbolOffset(*(Sym.MCSym)));
      }
    }
  }

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

void XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::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 XCOFFObjectWriter::getExceptionSectionSize() {
  unsigned EntryNum = 0;

  for (auto it = ExceptionSection.ExceptionTable.begin();
       it != ExceptionSection.ExceptionTable.end(); ++it)
    // The size() gets +1 to account for the initial entry containing the
    // symbol table index.
    EntryNum += it->second.Entries.size() + 1;

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

unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol *Symbol) {
  unsigned EntryNum = 0;
  for (auto it = ExceptionSection.ExceptionTable.begin();
       it != ExceptionSection.ExceptionTable.end(); ++it) {
    if (Symbol == it->second.FunctionSymbol)
      break;
    EntryNum += it->second.Entries.size() + 1;
  }
  return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
                               : XCOFF::ExceptionSectionEntrySize32);
}

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

void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
  // The symbol table starts with all the C_FILE symbols.
  uint32_t SymbolTableIndex = 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 = Layout.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 = Layout.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 = Layout.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 XCOFFObjectWriter::writeSectionForControlSectionEntry(
    const MCAssembler &Asm, const MCAsmLayout &Layout,
    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, Layout);
      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 XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
    const MCAssembler &Asm, const MCAsmLayout &Layout,
    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, Layout);

  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 XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
    const MCAssembler &Asm, const MCAsmLayout &Layout,
    ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation) {
  for (auto it = ExceptionEntry.ExceptionTable.begin();
       it != ExceptionEntry.ExceptionTable.end(); it++) {
    // For every symbol that has exception entries, you must start the entries
    // with an initial symbol table index entry
    W.write<uint32_t>(SymbolIndexMap[it->second.FunctionSymbol]);
    if (is64Bit()) {
      // 4-byte padding on 64-bit.
      W.OS.write_zeros(4);
    }
    W.OS.write_zeros(2);
    for (auto &TrapEntry : it->second.Entries) {
      writeWord(TrapEntry.TrapAddress);
      W.write<uint8_t>(TrapEntry.Lang);
      W.write<uint8_t>(TrapEntry.Reason);
    }
  }

  CurrentAddressLocation += getExceptionSectionSize();
}

void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry(
    const MCAssembler &Asm, const MCAsmLayout &Layout,
    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<XCOFFObjectWriter>(std::move(MOTW), OS);
}
