//===-- 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;

  // 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;

  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;
  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;
};

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;

  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 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);

  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, support::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) {}

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();

  // 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.find(MCSec) == SectionMap.end() &&
           "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.find(ContainingCsect) != SectionMap.end() &&
           "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());
  }

  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.find(Sym) != SymbolIndexMap.end()
               ? 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.find(SymASec) != SectionMap.end() &&
         "Expected containing csect to exist in map.");

  const uint32_t Index = getIndex(SymA, SymASec);
  if (Type == XCOFF::RelocationType::R_POS ||
      Type == XCOFF::RelocationType::R_TLS)
    // 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 +
                              Layout.getFragmentOffset(Fragment) +
                              Fixup.getOffset();
    // The FixedValue should be the difference between SymA csect address and BR
    // instr address plus any constant value.
    FixedValue =
        SectionMap[SymASec]->Address - BRInstrAddress + Target.getConstant();
  }

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

  XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
  MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
  assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
         "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.find(SymBSec) != SectionMap.end() &&
         "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);
}

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);
}

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.
  // The n_name of a C_FILE symbol is the source file's name when no auxiliary
  // entries are present.
  for (const std::pair<std::string, size_t> &F : FileNames) {
    writeSymbolEntry(F.first, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG,
                     /*SymbolType=*/0, XCOFF::C_FILE,
                     /*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;

    Sec->FileOffsetToData = RawPointer;
    RawPointer += Sec->Size;
    if (RawPointer > MaxRawDataSize)
      report_fatal_error("Section raw data overflowed this object file.");
  }

  if (!DwarfSections.empty()) {
    RawPointer += PaddingsBeforeDwarf;
    for (auto &DwarfSection : DwarfSections) {
      DwarfSection.FileOffsetToData = RawPointer;
      RawPointer += DwarfSection.MemorySize;
      if (RawPointer > MaxRawDataSize)
        report_fatal_error("Section raw data overflowed this object file.");
    }
  }

  if (hasExceptionSection()) {
    ExceptionSection.FileOffsetToData = RawPointer;
    RawPointer += ExceptionSection.Size;

    assert(RawPointer <= MaxRawDataSize &&
           "Section raw data overflowed this object file.");
  }

  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::assignAddressesAndIndices(const MCAsmLayout &Layout) {
  // The symbol table starts with all the C_FILE symbols.
  uint32_t SymbolTableIndex = FileNames.size();

  // 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);
  }

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

// 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);
}
