//===- llvm/CodeGen/TargetLoweringObjectFileImpl.cpp - Object File Info ---===//
//
// 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 classes used to handle lowerings specific to common
// object file formats.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/BinaryFormat/GOFF.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/CodeGen/BasicBlockSectionUtils.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmInfoDarwin.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCGOFFAttributes.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionGOFF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSectionWasm.h"
#include "llvm/MC/MCSectionXCOFF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCSymbolGOFF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Base64.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/Triple.h"
#include <cassert>
#include <string>

using namespace llvm;
using namespace dwarf;

extern cl::opt<bool> PreserveHotDataSectionPrefix;

static cl::opt<bool> JumpTableInFunctionSection(
    "jumptable-in-function-section", cl::Hidden, cl::init(false),
    cl::desc("Putting Jump Table in function section"));

static void GetObjCImageInfo(const Module &M, unsigned &Version,
                             unsigned &Flags, StringRef &Section) {
  SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
  M.getModuleFlagsMetadata(ModuleFlags);

  for (const auto &MFE: ModuleFlags) {
    // Ignore flags with 'Require' behaviour.
    if (MFE.Behavior == Module::Require)
      continue;

    StringRef Key = MFE.Key->getString();
    if (Key == "Objective-C Image Info Version") {
      Version = mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue();
    } else if (Key == "Objective-C Garbage Collection" ||
               Key == "Objective-C GC Only" ||
               Key == "Objective-C Is Simulated" ||
               Key == "Objective-C Class Properties" ||
               Key == "Objective-C Image Swift Version") {
      Flags |= mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue();
    } else if (Key == "Objective-C Image Info Section") {
      Section = cast<MDString>(MFE.Val)->getString();
    }
    // Backend generates L_OBJC_IMAGE_INFO from Swift ABI version + major + minor +
    // "Objective-C Garbage Collection".
    else if (Key == "Swift ABI Version") {
      Flags |= (mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue()) << 8;
    } else if (Key == "Swift Major Version") {
      Flags |= (mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue()) << 24;
    } else if (Key == "Swift Minor Version") {
      Flags |= (mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue()) << 16;
    }
  }
}

//===----------------------------------------------------------------------===//
//                                  ELF
//===----------------------------------------------------------------------===//

void TargetLoweringObjectFileELF::initialize(MCContext &Ctx,
                                             const TargetMachine &TgtM,
                                             const Module &M) {
  TargetLoweringObjectFile::initialize(Ctx, TgtM, M);

  const CodeModel::Model CM = TgtM.getCodeModel();
  InitializeELF(TgtM.Options.UseInitArray);

  switch (TgtM.getTargetTriple().getArch()) {
  case Triple::arm:
  case Triple::armeb:
  case Triple::thumb:
  case Triple::thumbeb:
    if (M.getExceptionModel() == ExceptionHandling::ARM)
      break;
    // Fallthrough if not using EHABI
    [[fallthrough]];
  case Triple::ppc:
  case Triple::ppcle:
  case Triple::x86:
    PersonalityEncoding = isPositionIndependent()
                              ? dwarf::DW_EH_PE_indirect |
                                    dwarf::DW_EH_PE_pcrel |
                                    dwarf::DW_EH_PE_sdata4
                              : dwarf::DW_EH_PE_absptr;
    LSDAEncoding = isPositionIndependent()
                       ? dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
                       : dwarf::DW_EH_PE_absptr;
    TTypeEncoding = isPositionIndependent()
                        ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
                              dwarf::DW_EH_PE_sdata4
                        : dwarf::DW_EH_PE_absptr;
    break;
  case Triple::x86_64: {
    // The large EH encoding forces 64-bit-wide EH pointers regardless of the
    // code model, so treat it like the Large code model when selecting
    // encodings below.
    const CodeModel::Model EHCM =
        TgtM.Options.MCOptions.LargeEHEncoding ? CodeModel::Large : CM;
    if (isPositionIndependent()) {
      PersonalityEncoding =
          dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
          ((EHCM == CodeModel::Small || EHCM == CodeModel::Medium)
               ? dwarf::DW_EH_PE_sdata4
               : dwarf::DW_EH_PE_sdata8);
      LSDAEncoding = dwarf::DW_EH_PE_pcrel |
                     (EHCM == CodeModel::Small ? dwarf::DW_EH_PE_sdata4
                                               : dwarf::DW_EH_PE_sdata8);
      TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
                      ((EHCM == CodeModel::Small || EHCM == CodeModel::Medium)
                           ? dwarf::DW_EH_PE_sdata4
                           : dwarf::DW_EH_PE_sdata8);
    } else {
      PersonalityEncoding =
          (EHCM == CodeModel::Small || EHCM == CodeModel::Medium)
              ? dwarf::DW_EH_PE_udata4
              : dwarf::DW_EH_PE_absptr;
      LSDAEncoding = (EHCM == CodeModel::Small) ? dwarf::DW_EH_PE_udata4
                                                : dwarf::DW_EH_PE_absptr;
      TTypeEncoding = (EHCM == CodeModel::Small) ? dwarf::DW_EH_PE_udata4
                                                 : dwarf::DW_EH_PE_absptr;
    }
    break;
  }
  case Triple::hexagon:
    PersonalityEncoding = dwarf::DW_EH_PE_absptr;
    LSDAEncoding = dwarf::DW_EH_PE_absptr;
    TTypeEncoding = dwarf::DW_EH_PE_absptr;
    if (isPositionIndependent()) {
      PersonalityEncoding |= dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel;
      LSDAEncoding |= dwarf::DW_EH_PE_pcrel;
      TTypeEncoding |= dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel;
    }
    break;
  case Triple::aarch64:
  case Triple::aarch64_be:
  case Triple::aarch64_32:
    // The small model guarantees static code/data size < 4GB, but not where it
    // will be in memory. Most of these could end up >2GB away so even a signed
    // pc-relative 32-bit address is insufficient, theoretically.
    //
    // Use DW_EH_PE_indirect even for -fno-pic to avoid copy relocations.
    LSDAEncoding = dwarf::DW_EH_PE_pcrel |
                   (TgtM.getTargetTriple().getEnvironment() == Triple::GNUILP32
                        ? dwarf::DW_EH_PE_sdata4
                        : dwarf::DW_EH_PE_sdata8);
    PersonalityEncoding = LSDAEncoding | dwarf::DW_EH_PE_indirect;
    TTypeEncoding = LSDAEncoding | dwarf::DW_EH_PE_indirect;
    break;
  case Triple::lanai:
    LSDAEncoding = dwarf::DW_EH_PE_absptr;
    PersonalityEncoding = dwarf::DW_EH_PE_absptr;
    TTypeEncoding = dwarf::DW_EH_PE_absptr;
    break;
  case Triple::mips:
  case Triple::mipsel:
  case Triple::mips64:
  case Triple::mips64el:
    // MIPS uses indirect pointer to refer personality functions and types, so
    // that the eh_frame section can be read-only. DW.ref.personality will be
    // generated for relocation.
    PersonalityEncoding = dwarf::DW_EH_PE_indirect;
    // FIXME: The N64 ABI probably ought to use DW_EH_PE_sdata8 but we can't
    //        identify N64 from just a triple.
    TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
                    dwarf::DW_EH_PE_sdata4;

    // FreeBSD must be explicit about the data size and using pcrel since it's
    // assembler/linker won't do the automatic conversion that the Linux tools
    // do.
    if (isPositionIndependent() || TgtM.getTargetTriple().isOSFreeBSD()) {
      PersonalityEncoding |= dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
      LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
    }
    break;
  case Triple::ppc64:
  case Triple::ppc64le:
    PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
      dwarf::DW_EH_PE_udata8;
    LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8;
    TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
      dwarf::DW_EH_PE_udata8;
    break;
  case Triple::sparcel:
  case Triple::sparc:
    if (isPositionIndependent()) {
      LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
      PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
        dwarf::DW_EH_PE_sdata4;
      TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
        dwarf::DW_EH_PE_sdata4;
    } else {
      LSDAEncoding = dwarf::DW_EH_PE_absptr;
      PersonalityEncoding = dwarf::DW_EH_PE_absptr;
      TTypeEncoding = dwarf::DW_EH_PE_absptr;
    }
    CallSiteEncoding = dwarf::DW_EH_PE_udata4;
    break;
  case Triple::riscv32:
  case Triple::riscv64:
  case Triple::riscv32be:
  case Triple::riscv64be:
    LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
    PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
                          dwarf::DW_EH_PE_sdata4;
    TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
                    dwarf::DW_EH_PE_sdata4;
    CallSiteEncoding = dwarf::DW_EH_PE_udata4;
    break;
  case Triple::sparcv9:
    LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
    if (isPositionIndependent()) {
      PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
        dwarf::DW_EH_PE_sdata4;
      TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
        dwarf::DW_EH_PE_sdata4;
    } else {
      PersonalityEncoding = dwarf::DW_EH_PE_absptr;
      TTypeEncoding = dwarf::DW_EH_PE_absptr;
    }
    break;
  case Triple::systemz:
    // All currently-defined code models guarantee that 4-byte PC-relative
    // values will be in range.
    if (isPositionIndependent()) {
      PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
        dwarf::DW_EH_PE_sdata4;
      LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
      TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
        dwarf::DW_EH_PE_sdata4;
    } else {
      PersonalityEncoding = dwarf::DW_EH_PE_absptr;
      LSDAEncoding = dwarf::DW_EH_PE_absptr;
      TTypeEncoding = dwarf::DW_EH_PE_absptr;
    }
    break;
  case Triple::loongarch32:
  case Triple::loongarch64:
    LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
    PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
                          dwarf::DW_EH_PE_sdata4;
    TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
                    dwarf::DW_EH_PE_sdata4;
    break;
  default:
    break;
  }

  SmallVector<GlobalValue *, 4> Vec;
  collectUsedGlobalVariables(M, Vec, false);
  for (GlobalValue *GV : Vec)
    if (auto *GO = dyn_cast<GlobalObject>(GV))
      Used.insert(GO);
}

void TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer,
                                                     const Module &M) const {
  auto &C = getContext();

  emitLinkerDirectives(Streamer, M);

  if (NamedMDNode *DependentLibraries = M.getNamedMetadata("llvm.dependent-libraries")) {
    auto *S = C.getELFSection(".deplibs", ELF::SHT_LLVM_DEPENDENT_LIBRARIES,
                              ELF::SHF_MERGE | ELF::SHF_STRINGS, 1);

    Streamer.switchSection(S);

    for (const auto *Operand : DependentLibraries->operands()) {
      Streamer.emitBytes(
          cast<MDString>(cast<MDNode>(Operand)->getOperand(0))->getString());
      Streamer.emitInt8(0);
    }
  }

  emitPseudoProbeDescMetadata(Streamer, M);

  if (NamedMDNode *LLVMStats = M.getNamedMetadata("llvm.stats")) {
    // Emit the metadata for llvm statistics into .llvm_stats section, which is
    // formatted as a list of key/value pair, the value is base64 encoded.
    auto *S = C.getObjectFileInfo()->getLLVMStatsSection();
    Streamer.switchSection(S);
    for (const auto *Operand : LLVMStats->operands()) {
      const auto *MD = cast<MDNode>(Operand);
      assert(MD->getNumOperands() % 2 == 0 &&
             ("Operand num should be even for a list of key/value pair"));
      for (size_t I = 0; I < MD->getNumOperands(); I += 2) {
        // Encode the key string size.
        auto *Key = cast<MDString>(MD->getOperand(I));
        Streamer.emitULEB128IntValue(Key->getString().size());
        Streamer.emitBytes(Key->getString());
        // Encode the value into a Base64 string.
        std::string Value = encodeBase64(
            Twine(mdconst::dyn_extract<ConstantInt>(MD->getOperand(I + 1))
                      ->getZExtValue())
                .str());
        Streamer.emitULEB128IntValue(Value.size());
        Streamer.emitBytes(Value);
      }
    }
  }

  unsigned Version = 0;
  unsigned Flags = 0;
  StringRef Section;

  GetObjCImageInfo(M, Version, Flags, Section);
  if (!Section.empty()) {
    auto *S = C.getELFSection(Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
    Streamer.switchSection(S);
    Streamer.emitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO")));
    Streamer.emitInt32(Version);
    Streamer.emitInt32(Flags);
    Streamer.addBlankLine();
  }

  emitCGProfileMetadata(Streamer, M);
}

void TargetLoweringObjectFileELF::emitLinkerDirectives(MCStreamer &Streamer,
                                                       const Module &M) const {
  auto &C = getContext();
  if (NamedMDNode *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
    auto *S = C.getELFSection(".linker-options", ELF::SHT_LLVM_LINKER_OPTIONS,
                              ELF::SHF_EXCLUDE);

    Streamer.switchSection(S);

    for (const auto *Operand : LinkerOptions->operands()) {
      if (cast<MDNode>(Operand)->getNumOperands() != 2)
        report_fatal_error("invalid llvm.linker.options");
      for (const auto &Option : cast<MDNode>(Operand)->operands()) {
        Streamer.emitBytes(cast<MDString>(Option)->getString());
        Streamer.emitInt8(0);
      }
    }
  }
}

MCSymbol *TargetLoweringObjectFileELF::getCFIPersonalitySymbol(
    const GlobalValue *GV, const TargetMachine &TM,
    MachineModuleInfo *MMI) const {
  unsigned Encoding = getPersonalityEncoding();
  if ((Encoding & 0x80) == DW_EH_PE_indirect)
    return getContext().getOrCreateSymbol(StringRef("DW.ref.") +
                                          TM.getSymbol(GV)->getName());
  if ((Encoding & 0x70) == DW_EH_PE_absptr)
    return TM.getSymbol(GV);
  report_fatal_error("We do not support this DWARF encoding yet!");
}

void TargetLoweringObjectFileELF::emitPersonalityValue(
    MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
    const MachineModuleInfo *MMI) const {
  SmallString<64> NameData("DW.ref.");
  NameData += Sym->getName();
  auto *Label =
      static_cast<MCSymbolELF *>(getContext().getOrCreateSymbol(NameData));
  Streamer.emitSymbolAttribute(Label, MCSA_Hidden);
  Streamer.emitSymbolAttribute(Label, MCSA_Weak);
  unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP;
  MCSection *Sec = getContext().getELFNamedSection(".data", Label->getName(),
                                                   ELF::SHT_PROGBITS, Flags, 0);
  unsigned Size = DL.getPointerSize();
  Streamer.switchSection(Sec);
  Streamer.emitValueToAlignment(DL.getPointerABIAlignment(0));
  Streamer.emitSymbolAttribute(Label, MCSA_ELF_TypeObject);
  const MCExpr *E = MCConstantExpr::create(Size, getContext());
  Streamer.emitELFSize(Label, E);
  Streamer.emitLabel(Label);

  emitPersonalityValueImpl(Streamer, DL, Sym, MMI);
}

void TargetLoweringObjectFileELF::emitPersonalityValueImpl(
    MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
    const MachineModuleInfo *MMI) const {
  Streamer.emitSymbolValue(Sym, DL.getPointerSize());
}

const MCExpr *TargetLoweringObjectFileELF::getTTypeGlobalReference(
    const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
    MachineModuleInfo *MMI, MCStreamer &Streamer) const {
  if (Encoding & DW_EH_PE_indirect) {
    MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo<MachineModuleInfoELF>();

    MCSymbol *SSym = getSymbolWithGlobalValueBase(GV, ".DW.stub", TM);

    // Add information about the stub reference to ELFMMI so that the stub
    // gets emitted by the asmprinter.
    MachineModuleInfoImpl::StubValueTy &StubSym = ELFMMI.getGVStubEntry(SSym);
    if (!StubSym.getPointer()) {
      MCSymbol *Sym = TM.getSymbol(GV);
      StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
    }

    return TargetLoweringObjectFile::
      getTTypeReference(MCSymbolRefExpr::create(SSym, getContext()),
                        Encoding & ~DW_EH_PE_indirect, Streamer);
  }

  return TargetLoweringObjectFile::getTTypeGlobalReference(GV, Encoding, TM,
                                                           MMI, Streamer);
}

static SectionKind getELFKindForNamedSection(StringRef Name, SectionKind K) {
  // N.B.: The defaults used in here are not the same ones used in MC.
  // We follow gcc, MC follows gas. For example, given ".section .eh_frame",
  // both gas and MC will produce a section with no flags. Given
  // section(".eh_frame") gcc will produce:
  //
  //   .section   .eh_frame,"a",@progbits

  if (Name == getInstrProfSectionName(IPSK_covmap, Triple::ELF,
                                      /*AddSegmentInfo=*/false) ||
      Name == getInstrProfSectionName(IPSK_covfun, Triple::ELF,
                                      /*AddSegmentInfo=*/false) ||
      Name == getInstrProfSectionName(IPSK_covdata, Triple::ELF,
                                      /*AddSegmentInfo=*/false) ||
      Name == getInstrProfSectionName(IPSK_covname, Triple::ELF,
                                      /*AddSegmentInfo=*/false) ||
      Name == ".llvmbc" || Name == ".llvmcmd")
    return SectionKind::getMetadata();

  if (!Name.starts_with(".")) return K;

  // Default implementation based on some magic section names.
  if (Name == ".bss" || Name.starts_with(".bss.") ||
      Name.starts_with(".gnu.linkonce.b.") ||
      Name.starts_with(".llvm.linkonce.b.") || Name == ".sbss" ||
      Name.starts_with(".sbss.") || Name.starts_with(".gnu.linkonce.sb.") ||
      Name.starts_with(".llvm.linkonce.sb."))
    return SectionKind::getBSS();

  if (Name == ".tdata" || Name.starts_with(".tdata.") ||
      Name.starts_with(".gnu.linkonce.td.") ||
      Name.starts_with(".llvm.linkonce.td."))
    return SectionKind::getThreadData();

  if (Name == ".tbss" || Name.starts_with(".tbss.") ||
      Name.starts_with(".gnu.linkonce.tb.") ||
      Name.starts_with(".llvm.linkonce.tb."))
    return SectionKind::getThreadBSS();

  return K;
}

static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
  return SectionName.consume_front(Prefix) &&
         (SectionName.empty() || SectionName[0] == '.');
}

static unsigned getELFSectionType(StringRef Name, SectionKind K) {
  // Use SHT_NOTE for section whose name starts with ".note" to allow
  // emitting ELF notes from C variable declaration.
  // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77609
  if (Name.starts_with(".note"))
    return ELF::SHT_NOTE;

  if (hasPrefix(Name, ".init_array"))
    return ELF::SHT_INIT_ARRAY;

  if (hasPrefix(Name, ".fini_array"))
    return ELF::SHT_FINI_ARRAY;

  if (hasPrefix(Name, ".preinit_array"))
    return ELF::SHT_PREINIT_ARRAY;

  if (hasPrefix(Name, ".llvm.offloading"))
    return ELF::SHT_LLVM_OFFLOADING;
  if (Name == ".llvm.lto")
    return ELF::SHT_LLVM_LTO;

  if (K.isBSS() || K.isThreadBSS())
    return ELF::SHT_NOBITS;

  return ELF::SHT_PROGBITS;
}

static unsigned getELFSectionFlags(SectionKind K, const Triple &T) {
  unsigned Flags = 0;

  if (!K.isMetadata() && !K.isExclude())
    Flags |= ELF::SHF_ALLOC;

  if (K.isExclude())
    Flags |= ELF::SHF_EXCLUDE;

  if (K.isText())
    Flags |= ELF::SHF_EXECINSTR;

  if (K.isExecuteOnly()) {
    if (T.isAArch64())
      Flags |= ELF::SHF_AARCH64_PURECODE;
    else if (T.isARM() || T.isThumb())
      Flags |= ELF::SHF_ARM_PURECODE;
  }

  if (K.isWriteable())
    Flags |= ELF::SHF_WRITE;

  if (K.isThreadLocal())
    Flags |= ELF::SHF_TLS;

  if (K.isMergeableCString() || K.isMergeableConst())
    Flags |= ELF::SHF_MERGE;

  if (K.isMergeableCString())
    Flags |= ELF::SHF_STRINGS;

  return Flags;
}

static const Comdat *getELFComdat(const GlobalValue *GV) {
  const Comdat *C = GV->getComdat();
  if (!C)
    return nullptr;

  if (C->getSelectionKind() != Comdat::Any &&
      C->getSelectionKind() != Comdat::NoDeduplicate)
    report_fatal_error("ELF COMDATs only support SelectionKind::Any and "
                       "SelectionKind::NoDeduplicate, '" +
                       C->getName() + "' cannot be lowered.");

  return C;
}

static const MCSymbolELF *getLinkedToSymbol(const GlobalObject *GO,
                                            const TargetMachine &TM) {
  MDNode *MD = GO->getMetadata(LLVMContext::MD_associated);
  if (!MD)
    return nullptr;

  auto *VM = cast<ValueAsMetadata>(MD->getOperand(0).get());
  auto *OtherGV = dyn_cast<GlobalValue>(VM->getValue());
  return OtherGV ? static_cast<const MCSymbolELF *>(TM.getSymbol(OtherGV))
                 : nullptr;
}

static unsigned getEntrySizeForKind(SectionKind Kind) {
  if (Kind.isMergeable1ByteCString())
    return 1;
  else if (Kind.isMergeable2ByteCString())
    return 2;
  else if (Kind.isMergeable4ByteCString())
    return 4;
  else if (Kind.isMergeableConst4())
    return 4;
  else if (Kind.isMergeableConst8())
    return 8;
  else if (Kind.isMergeableConst16())
    return 16;
  else if (Kind.isMergeableConst32())
    return 32;
  else {
    // We shouldn't have mergeable C strings or mergeable constants that we
    // didn't handle above.
    assert(!Kind.isMergeableCString() && "unknown string width");
    assert(!Kind.isMergeableConst() && "unknown data width");
    return 0;
  }
}

/// Return the section prefix name used by options FunctionsSections and
/// DataSections.
static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) {
  if (Kind.isText())
    return IsLarge ? ".ltext" : ".text";
  if (Kind.isReadOnly())
    return IsLarge ? ".lrodata" : ".rodata";
  if (Kind.isBSS())
    return IsLarge ? ".lbss" : ".bss";
  if (Kind.isThreadData())
    return ".tdata";
  if (Kind.isThreadBSS())
    return ".tbss";
  if (Kind.isData())
    return IsLarge ? ".ldata" : ".data";
  if (Kind.isReadOnlyWithRel())
    return IsLarge ? ".ldata.rel.ro" : ".data.rel.ro";
  llvm_unreachable("Unknown section kind");
}

static SmallString<128>
getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
                           Mangler &Mang, const TargetMachine &TM,
                           bool UniqueSectionName,
                           const MachineJumpTableEntry *JTE) {
  SmallString<128> Name =
      getSectionPrefixForGlobal(Kind, TM.isLargeGlobalValue(GO));
  unsigned EntrySize = getEntrySizeForKind(Kind);
  if (Kind.isMergeableCString()) {
    // We also need alignment here.
    // FIXME: this is getting the alignment of the character, not the
    // alignment of the global!
    Align Alignment = GO->getDataLayout().getPreferredAlign(
        cast<GlobalVariable>(GO));

    Name += ".str";
    Name += utostr(EntrySize);
    Name += ".";
    Name += utostr(Alignment.value());
  } else if (Kind.isMergeableConst()) {
    Name += ".cst";
    Name += utostr(EntrySize);
  }

  bool HasPrefix = false;
  SmallString<32> SectionPrefix;
  if (const auto *F = dyn_cast<Function>(GO)) {
    // Jump table hotness takes precedence over its enclosing function's hotness
    // if it's known. The function's section prefix is used if jump table entry
    // hotness is unknown.
    if (JTE && JTE->Hotness != MachineFunctionDataHotness::Unknown) {
      switch (JTE->Hotness) {
      case MachineFunctionDataHotness::Cold:
        raw_svector_ostream(SectionPrefix) << ".unlikely";
        break;
      case MachineFunctionDataHotness::Hot: {
        if (PreserveHotDataSectionPrefix)
          raw_svector_ostream(SectionPrefix) << ".hot";
        break;
      }
      default:
        llvm_unreachable("Unknown jump table hotness");
        break;
      }
    } else if (std::optional<StringRef> Prefix = F->getSectionPrefix())
      raw_svector_ostream(SectionPrefix) << "." << *Prefix;
  } else if (const auto *GV = dyn_cast<GlobalVariable>(GO)) {
    if (std::optional<StringRef> Prefix = GV->getSectionPrefix()) {
      raw_svector_ostream(SectionPrefix) << "." << *Prefix;
    }
  }

  if (!SectionPrefix.empty()) {
    bool AddSectionPrefix = true;
    if (Kind.isReadOnly() || Kind.isReadOnlyWithRel() || Kind.isData() ||
        Kind.isBSS()) {
      AddSectionPrefix =
          TM.getEnableStaticDataPartitioning() &&
          (!SectionPrefix.starts_with(".hot") || PreserveHotDataSectionPrefix);
    }

    if (AddSectionPrefix) {
      Name += SectionPrefix;
      HasPrefix = true;
    }
  }

  if (UniqueSectionName) {
    Name.push_back('.');
    TM.getNameWithPrefix(Name, GO, Mang, /*MayAlwaysUsePrivate*/true);
  } else if (HasPrefix)
    // For distinguishing between .text.${text-section-prefix}. (with trailing
    // dot) and .text.${function-name}
    Name.push_back('.');
  return Name;
}

namespace {
class LoweringDiagnosticInfo : public DiagnosticInfo {
  const Twine &Msg;

public:
  LoweringDiagnosticInfo(const Twine &DiagMsg LLVM_LIFETIME_BOUND,
                         DiagnosticSeverity Severity = DS_Error)
      : DiagnosticInfo(DK_Lowering, Severity), Msg(DiagMsg) {}
  void print(DiagnosticPrinter &DP) const override { DP << Msg; }
};
}

/// Calculate an appropriate unique ID for a section, and update Flags,
/// EntrySize and NextUniqueID where appropriate.
static unsigned
calcUniqueIDUpdateFlagsAndSize(const GlobalObject *GO, StringRef SectionName,
                               SectionKind Kind, const TargetMachine &TM,
                               MCContext &Ctx, Mangler &Mang, unsigned &Flags,
                               unsigned &EntrySize, unsigned &NextUniqueID,
                               const bool Retain, const bool ForceUnique) {
  // Increment uniqueID if we are forced to emit a unique section.
  // This works perfectly fine with section attribute or pragma section as the
  // sections with the same name are grouped together by the assembler.
  if (ForceUnique)
    return NextUniqueID++;

  // A section can have at most one associated section. Put each global with
  // MD_associated in a unique section.
  const bool Associated = GO->getMetadata(LLVMContext::MD_associated);
  if (Associated) {
    Flags |= ELF::SHF_LINK_ORDER;
    return NextUniqueID++;
  }

  if (Retain) {
    if (TM.getTargetTriple().isOSSolaris())
      Flags |= ELF::SHF_SUNW_NODISCARD;
    else if (Ctx.getAsmInfo().useIntegratedAssembler() ||
             Ctx.getAsmInfo().binutilsIsAtLeast(2, 36))
      Flags |= ELF::SHF_GNU_RETAIN;
    return NextUniqueID++;
  }

  // If two symbols with differing sizes end up in the same mergeable section
  // that section can be assigned an incorrect entry size. To avoid this we
  // usually put symbols of the same size into distinct mergeable sections with
  // the same name. Doing so relies on the ",unique ," assembly feature. This
  // feature is not available until binutils version 2.35
  // (https://sourceware.org/bugzilla/show_bug.cgi?id=25380).
  const bool SupportsUnique = Ctx.getAsmInfo().useIntegratedAssembler() ||
                              Ctx.getAsmInfo().binutilsIsAtLeast(2, 35);
  if (!SupportsUnique) {
    Flags &= ~ELF::SHF_MERGE;
    EntrySize = 0;
    return MCSection::NonUniqueID;
  }

  const bool SymbolMergeable = Flags & ELF::SHF_MERGE;
  const bool SeenSectionNameBefore =
      Ctx.isELFGenericMergeableSection(SectionName);
  // If this is the first occurrence of this section name, treat it as the
  // generic section
  if (!SymbolMergeable && !SeenSectionNameBefore) {
    if (TM.getSeparateNamedSections())
      return NextUniqueID++;
    else
      return MCSection::NonUniqueID;
  }

  // Symbols must be placed into sections with compatible entry sizes. Generate
  // unique sections for symbols that have not been assigned to compatible
  // sections.
  const auto PreviousID =
      Ctx.getELFUniqueIDForEntsize(SectionName, Flags, EntrySize);
  if (PreviousID &&
      (!TM.getSeparateNamedSections() || *PreviousID == MCSection::NonUniqueID))
    return *PreviousID;

  // If the user has specified the same section name as would be created
  // implicitly for this symbol e.g. .rodata.str1.1, then we don't need
  // to unique the section as the entry size for this symbol will be
  // compatible with implicitly created sections.
  SmallString<128> ImplicitSectionNameStem =
      getELFSectionNameForGlobal(GO, Kind, Mang, TM, false, /*MJTE=*/nullptr);
  if (SymbolMergeable &&
      Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) &&
      SectionName.starts_with(ImplicitSectionNameStem))
    return MCSection::NonUniqueID;

  // We have seen this section name before, but with different flags or entity
  // size. Create a new unique ID.
  return NextUniqueID++;
}

static std::tuple<StringRef, bool, unsigned, unsigned, unsigned>
getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM,
                    StringRef SectionName, SectionKind Kind) {
  StringRef Group = "";
  bool IsComdat = false;
  unsigned Flags = 0;
  if (const Comdat *C = getELFComdat(GO)) {
    Flags |= ELF::SHF_GROUP;
    Group = C->getName();
    IsComdat = C->getSelectionKind() == Comdat::Any;
  }
  if (TM.isLargeGlobalValue(GO))
    Flags |= ELF::SHF_X86_64_LARGE;

  unsigned Type, EntrySize;
  if (MDNode *MD = GO->getMetadata(LLVMContext::MD_elf_section_properties)) {
    Type = cast<ConstantAsMetadata>(MD->getOperand(0))
               ->getValue()
               ->getUniqueInteger()
               .getZExtValue();
    EntrySize = cast<ConstantAsMetadata>(MD->getOperand(1))
                    ->getValue()
                    ->getUniqueInteger()
                    .getZExtValue();
  } else {
    Type = getELFSectionType(SectionName, Kind);
    EntrySize = getEntrySizeForKind(Kind);
  }

  return {Group, IsComdat, Flags, Type, EntrySize};
}

static MCSection *selectExplicitSectionGlobal(const GlobalObject *GO,
                                              SectionKind Kind,
                                              const TargetMachine &TM,
                                              MCContext &Ctx, Mangler &Mang,
                                              unsigned &NextUniqueID,
                                              bool Retain, bool ForceUnique) {
  StringRef SectionName =
      TargetLoweringObjectFile::getCustomSectionName(GO, TM);

  // Infer section flags from the section name if we can.
  Kind = getELFKindForNamedSection(SectionName, Kind);

  unsigned Flags = getELFSectionFlags(Kind, GO->getParent()->getTargetTriple());
  auto [Group, IsComdat, ExtraFlags, Type, EntrySize] =
      getGlobalObjectInfo(GO, TM, SectionName, Kind);
  Flags |= ExtraFlags;

  const unsigned UniqueID = calcUniqueIDUpdateFlagsAndSize(
      GO, SectionName, Kind, TM, Ctx, Mang, Flags, EntrySize, NextUniqueID,
      Retain, ForceUnique);

  const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM);
  MCSectionELF *Section =
      Ctx.getELFSection(SectionName, Type, Flags, EntrySize, Group, IsComdat,
                        UniqueID, LinkedToSym);
  // Make sure that we did not get some other section with incompatible sh_link.
  // This should not be possible due to UniqueID code above.
  assert(Section->getLinkedToSymbol() == LinkedToSym &&
         "Associated symbol mismatch between sections");

  if (!(Ctx.getAsmInfo().useIntegratedAssembler() ||
        Ctx.getAsmInfo().binutilsIsAtLeast(2, 35))) {
    // If we are using GNU as before 2.35, then this symbol might have
    // been placed in an incompatible mergeable section. Emit an error if this
    // is the case to avoid creating broken output.
    if ((Section->getFlags() & ELF::SHF_MERGE) &&
        (Section->getEntrySize() != getEntrySizeForKind(Kind)))
      GO->getContext().diagnose(LoweringDiagnosticInfo(
          "Symbol '" + GO->getName() + "' from module '" +
          (GO->getParent() ? GO->getParent()->getSourceFileName() : "unknown") +
          "' required a section with entry-size=" +
          Twine(getEntrySizeForKind(Kind)) + " but was placed in section '" +
          SectionName + "' with entry-size=" + Twine(Section->getEntrySize()) +
          ": Explicit assignment by pragma or attribute of an incompatible "
          "symbol to this section?"));
  }

  return Section;
}

MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  return selectExplicitSectionGlobal(GO, Kind, TM, getContext(), getMangler(),
                                     NextUniqueID, Used.count(GO),
                                     /* ForceUnique = */false);
}

static MCSectionELF *selectELFSectionForGlobal(
    MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
    const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags,
    unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol,
    const MachineJumpTableEntry *MJTE = nullptr) {
  bool UniqueSectionName = false;
  unsigned UniqueID = MCSection::NonUniqueID;
  if (EmitUniqueSection) {
    if (TM.getUniqueSectionNames()) {
      UniqueSectionName = true;
    } else {
      UniqueID = *NextUniqueID;
      (*NextUniqueID)++;
    }
  }
  SmallString<128> Name =
      getELFSectionNameForGlobal(GO, Kind, Mang, TM, UniqueSectionName, MJTE);

  auto [Group, IsComdat, ExtraFlags, Type, EntrySize] =
      getGlobalObjectInfo(GO, TM, Name, Kind);
  Flags |= ExtraFlags;

  // Use 0 as the unique ID for execute-only text.
  if (Kind.isExecuteOnly())
    UniqueID = 0;
  return Ctx.getELFSection(Name, Type, Flags, EntrySize, Group, IsComdat,
                           UniqueID, AssociatedSymbol);
}

static MCSection *selectELFSectionForGlobal(
    MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
    const TargetMachine &TM, bool Retain, bool EmitUniqueSection,
    unsigned Flags, unsigned *NextUniqueID) {
  const MCSymbolELF *LinkedToSym = getLinkedToSymbol(GO, TM);
  if (LinkedToSym) {
    EmitUniqueSection = true;
    Flags |= ELF::SHF_LINK_ORDER;
  }
  if (Retain) {
    if (TM.getTargetTriple().isOSSolaris()) {
      EmitUniqueSection = true;
      Flags |= ELF::SHF_SUNW_NODISCARD;
    } else if (Ctx.getAsmInfo().useIntegratedAssembler() ||
               Ctx.getAsmInfo().binutilsIsAtLeast(2, 36)) {
      EmitUniqueSection = true;
      Flags |= ELF::SHF_GNU_RETAIN;
    }
  }
  if (GO->hasMetadata(LLVMContext::MD_elf_section_properties))
    EmitUniqueSection = true;

  MCSectionELF *Section = selectELFSectionForGlobal(
      Ctx, GO, Kind, Mang, TM, EmitUniqueSection, Flags,
      NextUniqueID, LinkedToSym);
  assert(Section->getLinkedToSymbol() == LinkedToSym);
  return Section;
}

MCSection *TargetLoweringObjectFileELF::SelectSectionForGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  unsigned Flags = getELFSectionFlags(Kind, GO->getParent()->getTargetTriple());

  // If we have -ffunction-section or -fdata-section then we should emit the
  // global value to a uniqued section specifically for it.
  bool EmitUniqueSection = false;
  if (!(Flags & ELF::SHF_MERGE) && !Kind.isCommon()) {
    if (Kind.isText())
      EmitUniqueSection = TM.getFunctionSections();
    else
      EmitUniqueSection = TM.getDataSections();
  }
  EmitUniqueSection |= GO->hasComdat();
  return selectELFSectionForGlobal(getContext(), GO, Kind, getMangler(), TM,
                                   Used.count(GO), EmitUniqueSection, Flags,
                                   &NextUniqueID);
}

MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction(
    const Function &F, const TargetMachine &TM) const {
  SectionKind Kind = SectionKind::getText();
  unsigned Flags = getELFSectionFlags(Kind, F.getParent()->getTargetTriple());
  // If the function's section names is pre-determined via pragma or a
  // section attribute, call selectExplicitSectionGlobal.
  if (F.hasSection())
    return selectExplicitSectionGlobal(
        &F, Kind, TM, getContext(), getMangler(), NextUniqueID,
        Used.count(&F), /* ForceUnique = */true);

  return selectELFSectionForGlobal(
      getContext(), &F, Kind, getMangler(), TM, Used.count(&F),
      /*EmitUniqueSection=*/true, Flags, &NextUniqueID);
}

MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
    const Function &F, const TargetMachine &TM) const {
  return getSectionForJumpTable(F, TM, /*JTE=*/nullptr);
}

MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
    const Function &F, const TargetMachine &TM,
    const MachineJumpTableEntry *JTE) const {
  // If the function can be removed, produce a unique section so that
  // the table doesn't prevent the removal.
  const Comdat *C = F.getComdat();
  bool EmitUniqueSection = TM.getFunctionSections() || C;
  if (!EmitUniqueSection && !TM.getEnableStaticDataPartitioning())
    return ReadOnlySection;

  return selectELFSectionForGlobal(getContext(), &F, SectionKind::getReadOnly(),
                                   getMangler(), TM, EmitUniqueSection,
                                   ELF::SHF_ALLOC, &NextUniqueID,
                                   /* AssociatedSymbol */ nullptr, JTE);
}

MCSection *TargetLoweringObjectFileELF::getSectionForLSDA(
    const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
  // If neither COMDAT nor function sections, use the monolithic LSDA section.
  // Re-use this path if LSDASection is null as in the Arm EHABI.
  if (!LSDASection || (!F.hasComdat() && !TM.getFunctionSections()))
    return LSDASection;

  const auto *LSDA = static_cast<const MCSectionELF *>(LSDASection);
  unsigned Flags = LSDA->getFlags();
  const MCSymbolELF *LinkedToSym = nullptr;
  StringRef Group;
  bool IsComdat = false;
  if (const Comdat *C = getELFComdat(&F)) {
    Flags |= ELF::SHF_GROUP;
    Group = C->getName();
    IsComdat = C->getSelectionKind() == Comdat::Any;
  }
  // Use SHF_LINK_ORDER to facilitate --gc-sections if we can use GNU ld>=2.36
  // or LLD, which support mixed SHF_LINK_ORDER & non-SHF_LINK_ORDER.
  if (TM.getFunctionSections() &&
      (getContext().getAsmInfo().useIntegratedAssembler() &&
       getContext().getAsmInfo().binutilsIsAtLeast(2, 36))) {
    Flags |= ELF::SHF_LINK_ORDER;
    LinkedToSym = static_cast<const MCSymbolELF *>(&FnSym);
  }

  // Append the function name as the suffix like GCC, assuming
  // -funique-section-names applies to .gcc_except_table sections.
  return getContext().getELFSection(
      (TM.getUniqueSectionNames() ? LSDA->getName() + "." + F.getName()
                                  : LSDA->getName()),
      LSDA->getType(), Flags, 0, Group, IsComdat, MCSection::NonUniqueID,
      LinkedToSym);
}

bool TargetLoweringObjectFileELF::shouldPutJumpTableInFunctionSection(
    bool UsesLabelDifference, const Function &F) const {
  // We can always create relative relocations, so use another section
  // that can be marked non-executable.
  return false;
}

/// Given a mergeable constant with the specified size and relocation
/// information, return a section that it should be placed in.
bool TargetLoweringObjectFileELF::isLargeConstant(const DataLayout &DL,
                                                  SectionKind Kind,
                                                  const Constant *C) const {
  if (!TM)
    return false;
  if (TM->getCodeModel() == CodeModel::Large)
    return TM->getTargetTriple().getArch() == Triple::x86_64;
  if (Kind.isMergeableCString() && C) {
    assert(C->getType()->isSized());
    return TM->isLargeDataSize(DL.getTypeAllocSize(C->getType()));
  }
  // Globals generated by the compiler, e.g. constant pool entries, are always
  // small under the x86-64 medium code model.
  return false;
}

MCSection *TargetLoweringObjectFileELF::getSectionForConstantImpl(
    const DataLayout &DL, SectionKind Kind, const Constant *C,
    StringRef SectionSuffix) const {
  auto &Context = getContext();
  unsigned MergeableCstFlags = ELF::SHF_ALLOC;
  if (Kind.isMergeableConst() || Kind.isMergeableCString())
    MergeableCstFlags |= ELF::SHF_MERGE;
  bool IsLarge = isLargeConstant(DL, Kind, C);
  if (IsLarge)
    MergeableCstFlags |= ELF::SHF_X86_64_LARGE;

  StringRef CstPrefix = IsLarge ? ".lrodata" : ".rodata";
  SmallString<32> SectionSuffixStr;
  if (!SectionSuffix.empty()) {
    SectionSuffixStr.push_back('.');
    SectionSuffixStr += SectionSuffix;
    SectionSuffixStr.push_back('.');
  }

  if (Kind.isMergeableConst4())
    return Context.getELFSection(CstPrefix + ".cst4" + SectionSuffixStr,
                                 ELF::SHT_PROGBITS, MergeableCstFlags, 4);
  if (Kind.isMergeableConst8())
    return Context.getELFSection(CstPrefix + ".cst8" + SectionSuffixStr,
                                 ELF::SHT_PROGBITS, MergeableCstFlags, 8);
  if (Kind.isMergeableConst16())
    return Context.getELFSection(CstPrefix + ".cst16" + SectionSuffixStr,
                                 ELF::SHT_PROGBITS, MergeableCstFlags, 16);
  if (Kind.isMergeableConst32())
    return Context.getELFSection(CstPrefix + ".cst32" + SectionSuffixStr,
                                 ELF::SHT_PROGBITS, MergeableCstFlags, 32);
  if (Kind.isReadOnly())
    return Context.getELFSection(
        CstPrefix + SectionSuffixStr, ELF::SHT_PROGBITS,
        ELF::SHF_ALLOC | (IsLarge ? ELF::SHF_X86_64_LARGE : 0));

  assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
  return Context.getELFSection(".data.rel.ro" + SectionSuffixStr,
                               ELF::SHT_PROGBITS,
                               ELF::SHF_ALLOC | ELF::SHF_WRITE);
}

MCSection *TargetLoweringObjectFileELF::getSectionForConstant(
    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
    const Function *F) const {
  return getSectionForConstantImpl(DL, Kind, C, "");
}

MCSection *TargetLoweringObjectFileELF::getSectionForConstant(
    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
    const Function *F, StringRef SectionSuffix) const {
  if (SectionSuffix.empty())
    return getSectionForConstant(DL, Kind, C, Alignment, F);

  return getSectionForConstantImpl(DL, Kind, C, SectionSuffix);
}

/// Returns a unique section for the given machine basic block.
MCSection *TargetLoweringObjectFileELF::getSectionForMachineBasicBlock(
    const Function &F, const MachineBasicBlock &MBB,
    const TargetMachine &TM) const {
  assert(MBB.isBeginSection() && "Basic block does not start a section!");
  unsigned UniqueID = MCSection::NonUniqueID;

  // For cold sections use the .text.split. prefix along with the parent
  // function name. All cold blocks for the same function go to the same
  // section. Similarly all exception blocks are grouped by symbol name
  // under the .text.eh prefix. For regular sections, we either use a unique
  // name, or a unique ID for the section.
  SmallString<128> Name;
  StringRef FunctionSectionName = MBB.getParent()->getSection()->getName();
  if (FunctionSectionName == ".text" ||
      FunctionSectionName.starts_with(".text.")) {
    // Function is in a regular .text section.
    StringRef FunctionName = MBB.getParent()->getName();
    if (MBB.getSectionID() == MBBSectionID::ColdSectionID) {
      Name += BBSectionsColdTextPrefix;
      Name += FunctionName;
    } else if (MBB.getSectionID() == MBBSectionID::ExceptionSectionID) {
      Name += ".text.eh.";
      Name += FunctionName;
    } else {
      Name += FunctionSectionName;
      if (TM.getUniqueBasicBlockSectionNames()) {
        if (!Name.ends_with("."))
          Name += ".";
        Name += MBB.getSymbol()->getName();
      } else {
        UniqueID = NextUniqueID++;
      }
    }
  } else {
    // If the original function has a custom non-dot-text section, then emit
    // all basic block sections into that section too, each with a unique id.
    Name = FunctionSectionName;
    UniqueID = NextUniqueID++;
  }

  unsigned Flags =
      static_cast<const MCSectionELF *>(MBB.getParent()->getSection())
          ->getFlags();
  std::string GroupName;
  if (F.hasComdat()) {
    Flags |= ELF::SHF_GROUP;
    GroupName = F.getComdat()->getName().str();
  }
  return getContext().getELFSection(Name, ELF::SHT_PROGBITS, Flags,
                                    0 /* Entry Size */, GroupName,
                                    F.hasComdat(), UniqueID, nullptr);
}

static MCSectionELF *getStaticStructorSection(MCContext &Ctx, bool UseInitArray,
                                              bool IsCtor, unsigned Priority,
                                              const MCSymbol *KeySym) {
  std::string Name;
  unsigned Type;
  unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE;
  StringRef Comdat = KeySym ? KeySym->getName() : "";

  if (KeySym)
    Flags |= ELF::SHF_GROUP;

  if (UseInitArray) {
    if (IsCtor) {
      Type = ELF::SHT_INIT_ARRAY;
      Name = ".init_array";
    } else {
      Type = ELF::SHT_FINI_ARRAY;
      Name = ".fini_array";
    }
    if (Priority != 65535) {
      Name += '.';
      Name += utostr(Priority);
    }
  } else {
    // The default scheme is .ctor / .dtor, so we have to invert the priority
    // numbering.
    if (IsCtor)
      Name = ".ctors";
    else
      Name = ".dtors";
    if (Priority != 65535)
      raw_string_ostream(Name) << format(".%05u", 65535 - Priority);
    Type = ELF::SHT_PROGBITS;
  }

  return Ctx.getELFSection(Name, Type, Flags, 0, Comdat, /*IsComdat=*/true);
}

MCSection *TargetLoweringObjectFileELF::getStaticCtorSection(
    unsigned Priority, const MCSymbol *KeySym) const {
  return getStaticStructorSection(getContext(), UseInitArray, true, Priority,
                                  KeySym);
}

MCSection *TargetLoweringObjectFileELF::getStaticDtorSection(
    unsigned Priority, const MCSymbol *KeySym) const {
  return getStaticStructorSection(getContext(), UseInitArray, false, Priority,
                                  KeySym);
}

const MCExpr *TargetLoweringObjectFileELF::lowerSymbolDifference(
    const MCSymbol *LHS, const MCSymbol *RHS, int64_t Addend,
    std::optional<int64_t> PCRelativeOffset) const {
  auto &Ctx = getContext();
  const MCExpr *Res;
  // Return a relocatable expression with the PLT specifier, %plt(GV) or
  // %plt(GV-RHS).
  if (PCRelativeOffset && PLTPCRelativeSpecifier) {
    Res = MCSymbolRefExpr::create(LHS, Ctx);
    // The current location is RHS plus *PCRelativeOffset. Compensate for it.
    Addend += *PCRelativeOffset;
    if (Addend)
      Res = MCBinaryExpr::createAdd(Res, MCConstantExpr::create(Addend, Ctx),
                                    Ctx);
    return MCSpecifierExpr::create(Res, PLTPCRelativeSpecifier, getContext());
  }

  if (!PLTRelativeSpecifier)
    return nullptr;
  Res = MCBinaryExpr::createSub(
      MCSymbolRefExpr::create(LHS, PLTRelativeSpecifier, Ctx),
      MCSymbolRefExpr::create(RHS, Ctx), Ctx);
  if (Addend)
    Res =
        MCBinaryExpr::createAdd(Res, MCConstantExpr::create(Addend, Ctx), Ctx);
  return Res;
}

// Reference the PLT entry of a function, optionally with a subtrahend (`RHS`).
const MCExpr *TargetLoweringObjectFileELF::lowerDSOLocalEquivalent(
    const MCSymbol *LHS, const MCSymbol *RHS, int64_t Addend,
    std::optional<int64_t> PCRelativeOffset, const TargetMachine &TM) const {
  if (RHS)
    return lowerSymbolDifference(LHS, RHS, Addend, PCRelativeOffset);

  // Only the legacy MCSymbolRefExpr::VariantKind approach is implemented.
  // Reference LHS@plt or LHS@plt - RHS.
  if (PLTRelativeSpecifier)
    return MCSymbolRefExpr::create(LHS, PLTRelativeSpecifier, getContext());
  return nullptr;
}

MCSection *TargetLoweringObjectFileELF::getSectionForCommandLines() const {
  // Use ".GCC.command.line" since this feature is to support clang's
  // -frecord-gcc-switches which in turn attempts to mimic GCC's switch of the
  // same name.
  return getContext().getELFSection(".GCC.command.line", ELF::SHT_PROGBITS,
                                    ELF::SHF_MERGE | ELF::SHF_STRINGS, 1);
}

void
TargetLoweringObjectFileELF::InitializeELF(bool UseInitArray_) {
  UseInitArray = UseInitArray_;
  MCContext &Ctx = getContext();
  if (!UseInitArray) {
    StaticCtorSection = Ctx.getELFSection(".ctors", ELF::SHT_PROGBITS,
                                          ELF::SHF_ALLOC | ELF::SHF_WRITE);

    StaticDtorSection = Ctx.getELFSection(".dtors", ELF::SHT_PROGBITS,
                                          ELF::SHF_ALLOC | ELF::SHF_WRITE);
    return;
  }

  StaticCtorSection = Ctx.getELFSection(".init_array", ELF::SHT_INIT_ARRAY,
                                        ELF::SHF_WRITE | ELF::SHF_ALLOC);
  StaticDtorSection = Ctx.getELFSection(".fini_array", ELF::SHT_FINI_ARRAY,
                                        ELF::SHF_WRITE | ELF::SHF_ALLOC);
}

//===----------------------------------------------------------------------===//
//                                 MachO
//===----------------------------------------------------------------------===//

TargetLoweringObjectFileMachO::TargetLoweringObjectFileMachO() {
  SupportIndirectSymViaGOTPCRel = true;
}

void TargetLoweringObjectFileMachO::initialize(MCContext &Ctx,
                                               const TargetMachine &TM,
                                               const Module &M) {
  TargetLoweringObjectFile::initialize(Ctx, TM, M);
  if (TM.getRelocationModel() == Reloc::Static) {
    StaticCtorSection = Ctx.getMachOSection("__TEXT", "__constructor", 0,
                                            SectionKind::getData());
    StaticDtorSection = Ctx.getMachOSection("__TEXT", "__destructor", 0,
                                            SectionKind::getData());
  } else {
    StaticCtorSection = Ctx.getMachOSection("__DATA", "__mod_init_func",
                                            MachO::S_MOD_INIT_FUNC_POINTERS,
                                            SectionKind::getData());
    StaticDtorSection = Ctx.getMachOSection("__DATA", "__mod_term_func",
                                            MachO::S_MOD_TERM_FUNC_POINTERS,
                                            SectionKind::getData());
  }

  PersonalityEncoding =
      dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
  LSDAEncoding = dwarf::DW_EH_PE_pcrel;
  TTypeEncoding =
      dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
}

MCSection *TargetLoweringObjectFileMachO::getStaticDtorSection(
    unsigned Priority, const MCSymbol *KeySym) const {
  return StaticDtorSection;
  // In userspace, we lower global destructors via atexit(), but kernel/kext
  // environments do not provide this function so we still need to support the
  // legacy way here.
  // See the -disable-atexit-based-global-dtor-lowering CodeGen flag for more
  // context.
}

void TargetLoweringObjectFileMachO::emitModuleMetadata(MCStreamer &Streamer,
                                                       const Module &M) const {
  // Emit the linker options if present.
  emitLinkerDirectives(Streamer, M);

  emitPseudoProbeDescMetadata(Streamer, M);

  unsigned VersionVal = 0;
  unsigned ImageInfoFlags = 0;
  StringRef SectionVal;

  GetObjCImageInfo(M, VersionVal, ImageInfoFlags, SectionVal);
  emitCGProfileMetadata(Streamer, M);

  // The section is mandatory. If we don't have it, then we don't have GC info.
  if (SectionVal.empty())
    return;

  StringRef Segment, Section;
  unsigned TAA = 0, StubSize = 0;
  bool TAAParsed;
  if (Error E = MCSectionMachO::ParseSectionSpecifier(
          SectionVal, Segment, Section, TAA, TAAParsed, StubSize)) {
    // If invalid, report the error with report_fatal_error.
    report_fatal_error("Invalid section specifier '" + Section +
                       "': " + toString(std::move(E)) + ".");
  }

  // Get the section.
  MCSectionMachO *S = getContext().getMachOSection(
      Segment, Section, TAA, StubSize, SectionKind::getData());
  Streamer.switchSection(S);
  Streamer.emitLabel(getContext().
                     getOrCreateSymbol(StringRef("L_OBJC_IMAGE_INFO")));
  Streamer.emitInt32(VersionVal);
  Streamer.emitInt32(ImageInfoFlags);
  Streamer.addBlankLine();
}

void TargetLoweringObjectFileMachO::emitLinkerDirectives(
    MCStreamer &Streamer, const Module &M) const {
  if (auto *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
    for (const auto *Option : LinkerOptions->operands()) {
      SmallVector<std::string, 4> StrOptions;
      for (const auto &Piece : cast<MDNode>(Option)->operands())
        StrOptions.push_back(std::string(cast<MDString>(Piece)->getString()));
      Streamer.emitLinkerOptions(StrOptions);
    }
  }
}

static void checkMachOComdat(const GlobalValue *GV) {
  const Comdat *C = GV->getComdat();
  if (!C)
    return;

  report_fatal_error("MachO doesn't support COMDATs, '" + C->getName() +
                     "' cannot be lowered.");
}

MCSection *TargetLoweringObjectFileMachO::getExplicitSectionGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {

  StringRef SectionName =
      TargetLoweringObjectFile::getCustomSectionName(GO, TM);

  // Parse the section specifier and create it if valid.
  StringRef Segment, Section;
  unsigned TAA = 0, StubSize = 0;
  bool TAAParsed;

  checkMachOComdat(GO);

  if (Error E = MCSectionMachO::ParseSectionSpecifier(
          SectionName, Segment, Section, TAA, TAAParsed, StubSize)) {
    // If invalid, report the error with report_fatal_error.
    report_fatal_error("Global variable '" + GO->getName() +
                       "' has an invalid section specifier '" +
                       GO->getSection() + "': " + toString(std::move(E)) + ".");
  }

  // Get the section.
  MCSectionMachO *S =
      getContext().getMachOSection(Segment, Section, TAA, StubSize, Kind);

  // If TAA wasn't set by ParseSectionSpecifier() above,
  // use the value returned by getMachOSection() as a default.
  if (!TAAParsed)
    TAA = S->getTypeAndAttributes();

  // Okay, now that we got the section, verify that the TAA & StubSize agree.
  // If the user declared multiple globals with different section flags, we need
  // to reject it here.
  if (S->getTypeAndAttributes() != TAA || S->getStubSize() != StubSize) {
    // If invalid, report the error with report_fatal_error.
    report_fatal_error("Global variable '" + GO->getName() +
                       "' section type or attributes does not match previous"
                       " section specifier");
  }

  return S;
}

MCSection *TargetLoweringObjectFileMachO::SelectSectionForGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  checkMachOComdat(GO);

  // Handle thread local data.
  if (Kind.isThreadBSS()) return TLSBSSSection;
  if (Kind.isThreadData()) return TLSDataSection;

  if (Kind.isText())
    return GO->isWeakForLinker() ? TextCoalSection : TextSection;

  // If this is weak/linkonce, put this in a coalescable section, either in text
  // or data depending on if it is writable.
  if (GO->isWeakForLinker()) {
    if (Kind.isReadOnly())
      return ConstTextCoalSection;
    if (Kind.isReadOnlyWithRel())
      return ConstDataCoalSection;
    return DataCoalSection;
  }

  // FIXME: Alignment check should be handled by section classifier.
  if (Kind.isMergeable1ByteCString() &&
      GO->getDataLayout().getPreferredAlign(
          cast<GlobalVariable>(GO)) < Align(32))
    return CStringSection;

  // Do not put 16-bit arrays in the UString section if they have an
  // externally visible label, this runs into issues with certain linker
  // versions.
  if (Kind.isMergeable2ByteCString() && !GO->hasExternalLinkage() &&
      GO->getDataLayout().getPreferredAlign(
          cast<GlobalVariable>(GO)) < Align(32))
    return UStringSection;

  // With MachO only variables whose corresponding symbol starts with 'l' or
  // 'L' can be merged, so we only try merging GVs with private linkage.
  if (GO->hasPrivateLinkage() && Kind.isMergeableConst()) {
    if (Kind.isMergeableConst4())
      return FourByteConstantSection;
    if (Kind.isMergeableConst8())
      return EightByteConstantSection;
    if (Kind.isMergeableConst16())
      return SixteenByteConstantSection;
  }

  // Otherwise, if it is readonly, but not something we can specially optimize,
  // just drop it in .const.
  if (Kind.isReadOnly())
    return ReadOnlySection;

  // If this is marked const, put it into a const section.  But if the dynamic
  // linker needs to write to it, put it in the data segment.
  if (Kind.isReadOnlyWithRel())
    return ConstDataSection;

  // Put zero initialized globals with strong external linkage in the
  // DATA, __common section with the .zerofill directive.
  if (Kind.isBSSExtern())
    return DataCommonSection;

  // Put zero initialized globals with local linkage in __DATA,__bss directive
  // with the .zerofill directive (aka .lcomm).
  if (Kind.isBSSLocal())
    return DataBSSSection;

  // Otherwise, just drop the variable in the normal data section.
  return DataSection;
}

MCSection *TargetLoweringObjectFileMachO::getSectionForConstant(
    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
    const Function *F) const {
  // If this constant requires a relocation, we have to put it in the data
  // segment, not in the text segment.
  if (Kind.isData() || Kind.isReadOnlyWithRel())
    return ConstDataSection;

  if (Kind.isMergeableConst4())
    return FourByteConstantSection;
  if (Kind.isMergeableConst8())
    return EightByteConstantSection;
  if (Kind.isMergeableConst16())
    return SixteenByteConstantSection;
  return ReadOnlySection;  // .const
}

MCSection *TargetLoweringObjectFileMachO::getSectionForCommandLines() const {
  return getContext().getMachOSection("__TEXT", "__command_line", 0,
                                      SectionKind::getReadOnly());
}

const MCExpr *TargetLoweringObjectFileMachO::getTTypeGlobalReference(
    const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
    MachineModuleInfo *MMI, MCStreamer &Streamer) const {
  // The mach-o version of this method defaults to returning a stub reference.

  if (Encoding & DW_EH_PE_indirect) {
    MachineModuleInfoMachO &MachOMMI =
      MMI->getObjFileInfo<MachineModuleInfoMachO>();

    MCSymbol *SSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr", TM);

    // Add information about the stub reference to MachOMMI so that the stub
    // gets emitted by the asmprinter.
    MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(SSym);
    if (!StubSym.getPointer()) {
      MCSymbol *Sym = TM.getSymbol(GV);
      StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
    }

    return TargetLoweringObjectFile::
      getTTypeReference(MCSymbolRefExpr::create(SSym, getContext()),
                        Encoding & ~DW_EH_PE_indirect, Streamer);
  }

  return TargetLoweringObjectFile::getTTypeGlobalReference(GV, Encoding, TM,
                                                           MMI, Streamer);
}

MCSymbol *TargetLoweringObjectFileMachO::getCFIPersonalitySymbol(
    const GlobalValue *GV, const TargetMachine &TM,
    MachineModuleInfo *MMI) const {
  // The mach-o version of this method defaults to returning a stub reference.
  MachineModuleInfoMachO &MachOMMI =
    MMI->getObjFileInfo<MachineModuleInfoMachO>();

  MCSymbol *SSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr", TM);

  // Add information about the stub reference to MachOMMI so that the stub
  // gets emitted by the asmprinter.
  MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(SSym);
  if (!StubSym.getPointer()) {
    MCSymbol *Sym = TM.getSymbol(GV);
    StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
  }

  return SSym;
}

const MCExpr *TargetLoweringObjectFileMachO::getIndirectSymViaGOTPCRel(
    const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV,
    int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
  // Although MachO 32-bit targets do not explicitly have a GOTPCREL relocation
  // as 64-bit do, we replace the GOT equivalent by accessing the final symbol
  // through a non_lazy_ptr stub instead. One advantage is that it allows the
  // computation of deltas to final external symbols. Example:
  //
  //    _extgotequiv:
  //       .long   _extfoo
  //
  //    _delta:
  //       .long   _extgotequiv-_delta
  //
  // is transformed to:
  //
  //    _delta:
  //       .long   L_extfoo$non_lazy_ptr-(_delta+0)
  //
  //       .section        __IMPORT,__pointers,non_lazy_symbol_pointers
  //    L_extfoo$non_lazy_ptr:
  //       .indirect_symbol        _extfoo
  //       .long   0
  //
  // The indirect symbol table (and sections of non_lazy_symbol_pointers type)
  // may point to both local (same translation unit) and global (other
  // translation units) symbols. Example:
  //
  // .section __DATA,__pointers,non_lazy_symbol_pointers
  // L1:
  //    .indirect_symbol _myGlobal
  //    .long 0
  // L2:
  //    .indirect_symbol _myLocal
  //    .long _myLocal
  //
  // If the symbol is local, instead of the symbol's index, the assembler
  // places the constant INDIRECT_SYMBOL_LOCAL into the indirect symbol table.
  // Then the linker will notice the constant in the table and will look at the
  // content of the symbol.
  MachineModuleInfoMachO &MachOMMI =
    MMI->getObjFileInfo<MachineModuleInfoMachO>();
  MCContext &Ctx = getContext();

  // The offset must consider the original displacement from the base symbol
  // since 32-bit targets don't have a GOTPCREL to fold the PC displacement.
  Offset = -MV.getConstant();
  const MCSymbol *BaseSym = MV.getSubSym();

  // Access the final symbol via sym$non_lazy_ptr and generate the appropriated
  // non_lazy_ptr stubs.
  SmallString<128> Name;
  StringRef Suffix = "$non_lazy_ptr";
  Name += MMI->getModule()->getDataLayout().getInternalSymbolPrefix();
  Name += Sym->getName();
  Name += Suffix;
  MCSymbol *Stub = Ctx.getOrCreateSymbol(Name);

  MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(Stub);

  if (!StubSym.getPointer())
    StubSym = MachineModuleInfoImpl::StubValueTy(const_cast<MCSymbol *>(Sym),
                                                 !GV->hasLocalLinkage());

  const MCExpr *BSymExpr = MCSymbolRefExpr::create(BaseSym, Ctx);
  const MCExpr *LHS = MCSymbolRefExpr::create(Stub, Ctx);

  if (!Offset)
    return MCBinaryExpr::createSub(LHS, BSymExpr, Ctx);

  const MCExpr *RHS =
    MCBinaryExpr::createAdd(BSymExpr, MCConstantExpr::create(Offset, Ctx), Ctx);
  return MCBinaryExpr::createSub(LHS, RHS, Ctx);
}

static bool canUsePrivateLabel(const MCAsmInfo &AsmInfo,
                               const MCSection &Section) {
  if (!MCAsmInfoDarwin::isSectionAtomizableBySymbols(Section))
    return true;

  // FIXME: we should be able to use private labels for sections that can't be
  // dead-stripped (there's no issue with blocking atomization there), but `ld
  // -r` sometimes drops the no_dead_strip attribute from sections so for safety
  // we don't allow it.
  return false;
}

void TargetLoweringObjectFileMachO::getNameWithPrefix(
    SmallVectorImpl<char> &OutName, const GlobalValue *GV,
    const TargetMachine &TM) const {
  bool CannotUsePrivateLabel = true;
  if (auto *GO = GV->getAliaseeObject()) {
    SectionKind GOKind = TargetLoweringObjectFile::getKindForGlobal(GO, TM);
    const MCSection *TheSection = SectionForGlobal(GO, GOKind, TM);
    CannotUsePrivateLabel = !canUsePrivateLabel(TM.getMCAsmInfo(), *TheSection);
  }
  getMangler().getNameWithPrefix(OutName, GV, CannotUsePrivateLabel);
}

//===----------------------------------------------------------------------===//
//                                  COFF
//===----------------------------------------------------------------------===//

static unsigned
getCOFFSectionFlags(SectionKind K, const TargetMachine &TM) {
  unsigned Flags = 0;
  bool isThumb = TM.getTargetTriple().getArch() == Triple::thumb;

  if (K.isMetadata())
    Flags |=
      COFF::IMAGE_SCN_MEM_DISCARDABLE;
  else if (K.isExclude())
    Flags |=
      COFF::IMAGE_SCN_LNK_REMOVE | COFF::IMAGE_SCN_MEM_DISCARDABLE;
  else if (K.isText())
    Flags |=
      COFF::IMAGE_SCN_MEM_EXECUTE |
      COFF::IMAGE_SCN_MEM_READ |
      COFF::IMAGE_SCN_CNT_CODE |
      (isThumb ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0);
  else if (K.isBSS())
    Flags |=
      COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
      COFF::IMAGE_SCN_MEM_READ |
      COFF::IMAGE_SCN_MEM_WRITE;
  else if (K.isThreadLocal())
    Flags |=
      COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
      COFF::IMAGE_SCN_MEM_READ |
      COFF::IMAGE_SCN_MEM_WRITE;
  else if (K.isReadOnly() || K.isReadOnlyWithRel())
    Flags |=
      COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
      COFF::IMAGE_SCN_MEM_READ;
  else if (K.isWriteable())
    Flags |=
      COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
      COFF::IMAGE_SCN_MEM_READ |
      COFF::IMAGE_SCN_MEM_WRITE;

  return Flags;
}

static const GlobalValue *getComdatGVForCOFF(const GlobalValue *GV) {
  const Comdat *C = GV->getComdat();
  assert(C && "expected GV to have a Comdat!");

  StringRef ComdatGVName = C->getName();
  const GlobalValue *ComdatGV = GV->getParent()->getNamedValue(ComdatGVName);
  if (!ComdatGV)
    report_fatal_error("Associative COMDAT symbol '" + ComdatGVName +
                       "' does not exist.");

  if (ComdatGV->getComdat() != C)
    report_fatal_error("Associative COMDAT symbol '" + ComdatGVName +
                       "' is not a key for its COMDAT.");

  return ComdatGV;
}

static int getSelectionForCOFF(const GlobalValue *GV) {
  if (const Comdat *C = GV->getComdat()) {
    const GlobalValue *ComdatKey = getComdatGVForCOFF(GV);
    if (const auto *GA = dyn_cast<GlobalAlias>(ComdatKey))
      ComdatKey = GA->getAliaseeObject();
    if (ComdatKey == GV) {
      switch (C->getSelectionKind()) {
      case Comdat::Any:
        return COFF::IMAGE_COMDAT_SELECT_ANY;
      case Comdat::ExactMatch:
        return COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH;
      case Comdat::Largest:
        return COFF::IMAGE_COMDAT_SELECT_LARGEST;
      case Comdat::NoDeduplicate:
        return COFF::IMAGE_COMDAT_SELECT_NODUPLICATES;
      case Comdat::SameSize:
        return COFF::IMAGE_COMDAT_SELECT_SAME_SIZE;
      }
    } else {
      return COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
    }
  }
  return 0;
}

MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  StringRef Name = TargetLoweringObjectFile::getCustomSectionName(GO, TM);
  if (Name == getInstrProfSectionName(IPSK_covmap, Triple::COFF,
                                      /*AddSegmentInfo=*/false) ||
      Name == getInstrProfSectionName(IPSK_covfun, Triple::COFF,
                                      /*AddSegmentInfo=*/false) ||
      Name == getInstrProfSectionName(IPSK_covdata, Triple::COFF,
                                      /*AddSegmentInfo=*/false) ||
      Name == getInstrProfSectionName(IPSK_covname, Triple::COFF,
                                      /*AddSegmentInfo=*/false) ||
      Name == ".llvmbc" || Name == ".llvmcmd")
    Kind = SectionKind::getMetadata();
  int Selection = 0;
  unsigned Characteristics = getCOFFSectionFlags(Kind, TM);
  StringRef COMDATSymName = "";
  if (GO->hasComdat()) {
    Selection = getSelectionForCOFF(GO);
    const GlobalValue *ComdatGV;
    if (Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
      ComdatGV = getComdatGVForCOFF(GO);
    else
      ComdatGV = GO;

    if (!ComdatGV->hasPrivateLinkage()) {
      MCSymbol *Sym = TM.getSymbol(ComdatGV);
      COMDATSymName = Sym->getName();
      Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
    } else {
      Selection = 0;
    }
  }

  return getContext().getCOFFSection(Name, Characteristics, COMDATSymName,
                                     Selection);
}

static StringRef getCOFFSectionNameForUniqueGlobal(SectionKind Kind) {
  if (Kind.isText())
    return ".text";
  if (Kind.isBSS())
    return ".bss";
  if (Kind.isThreadLocal())
    return ".tls$";
  if (Kind.isReadOnly() || Kind.isReadOnlyWithRel())
    return ".rdata";
  return ".data";
}

MCSection *TargetLoweringObjectFileCOFF::SelectSectionForGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  // If we have -ffunction-sections then we should emit the global value to a
  // uniqued section specifically for it.
  bool EmitUniquedSection;
  if (Kind.isText())
    EmitUniquedSection = TM.getFunctionSections();
  else
    EmitUniquedSection = TM.getDataSections();

  if ((EmitUniquedSection && !Kind.isCommon()) || GO->hasComdat()) {
    SmallString<256> Name = getCOFFSectionNameForUniqueGlobal(Kind);

    unsigned Characteristics = getCOFFSectionFlags(Kind, TM);

    Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
    int Selection = getSelectionForCOFF(GO);
    if (!Selection)
      Selection = COFF::IMAGE_COMDAT_SELECT_NODUPLICATES;
    const GlobalValue *ComdatGV;
    if (GO->hasComdat())
      ComdatGV = getComdatGVForCOFF(GO);
    else
      ComdatGV = GO;

    unsigned UniqueID = MCSection::NonUniqueID;
    if (EmitUniquedSection)
      UniqueID = NextUniqueID++;

    if (!ComdatGV->hasPrivateLinkage()) {
      MCSymbol *Sym = TM.getSymbol(ComdatGV);
      StringRef COMDATSymName = Sym->getName();

      if (const auto *F = dyn_cast<Function>(GO))
        if (std::optional<StringRef> Prefix = F->getSectionPrefix())
          raw_svector_ostream(Name) << '$' << *Prefix;

      // Append "$symbol" to the section name *before* IR-level mangling is
      // applied when targetting mingw. This is what GCC does, and the ld.bfd
      // COFF linker will not properly handle comdats otherwise.
      if (getContext().getTargetTriple().isOSCygMing())
        raw_svector_ostream(Name) << '$' << ComdatGV->getName();

      return getContext().getCOFFSection(Name, Characteristics, COMDATSymName,
                                         Selection, UniqueID);
    } else {
      SmallString<256> TmpData;
      getMangler().getNameWithPrefix(TmpData, GO, /*CannotUsePrivateLabel=*/true);
      return getContext().getCOFFSection(Name, Characteristics, TmpData,
                                         Selection, UniqueID);
    }
  }

  if (Kind.isText())
    return TextSection;

  if (Kind.isThreadLocal())
    return TLSDataSection;

  if (Kind.isReadOnly() || Kind.isReadOnlyWithRel())
    return ReadOnlySection;

  // Note: we claim that common symbols are put in BSSSection, but they are
  // really emitted with the magic .comm directive, which creates a symbol table
  // entry but not a section.
  if (Kind.isBSS() || Kind.isCommon())
    return BSSSection;

  return DataSection;
}

void TargetLoweringObjectFileCOFF::getNameWithPrefix(
    SmallVectorImpl<char> &OutName, const GlobalValue *GV,
    const TargetMachine &TM) const {
  bool CannotUsePrivateLabel = false;
  if (GV->hasPrivateLinkage() &&
      ((isa<Function>(GV) && TM.getFunctionSections()) ||
       (isa<GlobalVariable>(GV) && TM.getDataSections())))
    CannotUsePrivateLabel = true;

  getMangler().getNameWithPrefix(OutName, GV, CannotUsePrivateLabel);
}

MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable(
    const Function &F, const TargetMachine &TM) const {
  // If the function can be removed, produce a unique section so that
  // the table doesn't prevent the removal.
  const Comdat *C = F.getComdat();
  bool EmitUniqueSection = TM.getFunctionSections() || C;
  if (!EmitUniqueSection)
    return ReadOnlySection;

  // FIXME: we should produce a symbol for F instead.
  if (F.hasPrivateLinkage())
    return ReadOnlySection;

  MCSymbol *Sym = TM.getSymbol(&F);
  StringRef COMDATSymName = Sym->getName();

  SectionKind Kind = SectionKind::getReadOnly();
  StringRef SecName = getCOFFSectionNameForUniqueGlobal(Kind);
  unsigned Characteristics = getCOFFSectionFlags(Kind, TM);
  Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
  unsigned UniqueID = NextUniqueID++;

  return getContext().getCOFFSection(SecName, Characteristics, COMDATSymName,
                                     COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE,
                                     UniqueID);
}

bool TargetLoweringObjectFileCOFF::shouldPutJumpTableInFunctionSection(
    bool UsesLabelDifference, const Function &F) const {
  if (TM->getTargetTriple().getArch() == Triple::x86_64) {
    if (!JumpTableInFunctionSection) {
      // We can always create relative relocations, so use another section
      // that can be marked non-executable.
      return false;
    }
  }
  return TargetLoweringObjectFile::shouldPutJumpTableInFunctionSection(
    UsesLabelDifference, F);
}

void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
                                                      const Module &M) const {
  emitLinkerDirectives(Streamer, M);

  unsigned Version = 0;
  unsigned Flags = 0;
  StringRef Section;

  GetObjCImageInfo(M, Version, Flags, Section);
  if (!Section.empty()) {
    auto &C = getContext();
    auto *S = C.getCOFFSection(Section, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                                            COFF::IMAGE_SCN_MEM_READ);
    Streamer.switchSection(S);
    Streamer.emitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO")));
    Streamer.emitInt32(Version);
    Streamer.emitInt32(Flags);
    Streamer.addBlankLine();
  }

  emitCGProfileMetadata(Streamer, M);
  emitPseudoProbeDescMetadata(Streamer, M, [](MCStreamer &Streamer) {
    if (MCSymbol *Sym =
            static_cast<MCSectionCOFF *>(Streamer.getCurrentSectionOnly())
                ->getCOMDATSymbol())
      if (Sym->isUndefined()) {
        // COMDAT symbol must be external to perform deduplication.
        Streamer.emitSymbolAttribute(Sym, MCSA_Global);
        Streamer.emitLabel(Sym);
      }
  });
}

void TargetLoweringObjectFileCOFF::emitLinkerDirectives(MCStreamer &Streamer,
                                                        const Module &M) const {
  if (NamedMDNode *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
    // Emit the linker options to the linker .drectve section.  According to the
    // spec, this section is a space-separated string containing flags for
    // linker.
    MCSection *Sec = getDrectveSection();
    Streamer.switchSection(Sec);
    for (const auto *Option : LinkerOptions->operands()) {
      for (const auto &Piece : cast<MDNode>(Option)->operands()) {
        // Lead with a space for consistency with our dllexport implementation.
        std::string Directive(" ");
        Directive.append(std::string(cast<MDString>(Piece)->getString()));
        Streamer.emitBytes(Directive);
      }
    }
  }

  // Emit /EXPORT: flags for each exported global as necessary.
  std::string Flags;
  for (const GlobalValue &GV : M.global_values()) {
    raw_string_ostream OS(Flags);
    emitLinkerFlagsForGlobalCOFF(OS, &GV, getContext().getTargetTriple(),
                                 getMangler());
    if (!Flags.empty()) {
      Streamer.switchSection(getDrectveSection());
      Streamer.emitBytes(Flags);
    }
    Flags.clear();
  }

  // Emit /INCLUDE: flags for each used global as necessary.
  if (const auto *LU = M.getNamedGlobal("llvm.used")) {
    assert(LU->hasInitializer() && "expected llvm.used to have an initializer");
    assert(isa<ArrayType>(LU->getValueType()) &&
           "expected llvm.used to be an array type");
    if (const auto *A = cast<ConstantArray>(LU->getInitializer())) {
      for (const Value *Op : A->operands()) {
        const auto *GV = cast<GlobalValue>(Op->stripPointerCasts());
        // Global symbols with internal or private linkage are not visible to
        // the linker, and thus would cause an error when the linker tried to
        // preserve the symbol due to the `/include:` directive.
        if (GV->hasLocalLinkage())
          continue;

        raw_string_ostream OS(Flags);
        emitLinkerFlagsForUsedCOFF(OS, GV, getContext().getTargetTriple(),
                                   getMangler());

        if (!Flags.empty()) {
          Streamer.switchSection(getDrectveSection());
          Streamer.emitBytes(Flags);
        }
        Flags.clear();
      }
    }
  }
}

void TargetLoweringObjectFileCOFF::initialize(MCContext &Ctx,
                                              const TargetMachine &TM,
                                              const Module &M) {
  TargetLoweringObjectFile::initialize(Ctx, TM, M);
  const Triple &T = TM.getTargetTriple();
  if (T.isWindowsMSVCEnvironment() || T.isWindowsItaniumEnvironment()) {
    StaticCtorSection =
        Ctx.getCOFFSection(".CRT$XCU", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                                           COFF::IMAGE_SCN_MEM_READ);
    StaticDtorSection =
        Ctx.getCOFFSection(".CRT$XTX", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                                           COFF::IMAGE_SCN_MEM_READ);
  } else {
    StaticCtorSection = Ctx.getCOFFSection(
        ".ctors", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                      COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE);
    StaticDtorSection = Ctx.getCOFFSection(
        ".dtors", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                      COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE);
  }
}

static MCSectionCOFF *getCOFFStaticStructorSection(MCContext &Ctx,
                                                   const Triple &T, bool IsCtor,
                                                   unsigned Priority,
                                                   const MCSymbol *KeySym,
                                                   MCSectionCOFF *Default) {
  if (T.isWindowsMSVCEnvironment() || T.isWindowsItaniumEnvironment()) {
    // If the priority is the default, use .CRT$XCU, possibly associative.
    if (Priority == 65535)
      return Ctx.getAssociativeCOFFSection(Default, KeySym, 0);

    // Otherwise, we need to compute a new section name. Low priorities should
    // run earlier. The linker will sort sections ASCII-betically, and we need a
    // string that sorts between .CRT$XCA and .CRT$XCU. In the general case, we
    // make a name like ".CRT$XCT12345", since that runs before .CRT$XCU. Really
    // low priorities need to sort before 'L', since the CRT uses that
    // internally, so we use ".CRT$XCA00001" for them. We have a contract with
    // the frontend that "init_seg(compiler)" corresponds to priority 200 and
    // "init_seg(lib)" corresponds to priority 400, and those respectively use
    // 'C' and 'L' without the priority suffix. Priorities between 200 and 400
    // use 'C' with the priority as a suffix.
    SmallString<24> Name;
    char LastLetter = 'T';
    bool AddPrioritySuffix = Priority != 200 && Priority != 400;
    if (Priority < 200)
      LastLetter = 'A';
    else if (Priority < 400)
      LastLetter = 'C';
    else if (Priority == 400)
      LastLetter = 'L';
    raw_svector_ostream OS(Name);
    OS << ".CRT$X" << (IsCtor ? "C" : "T") << LastLetter;
    if (AddPrioritySuffix)
      OS << format("%05u", Priority);
    MCSectionCOFF *Sec = Ctx.getCOFFSection(
        Name, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ);
    return Ctx.getAssociativeCOFFSection(Sec, KeySym, 0);
  }

  std::string Name = IsCtor ? ".ctors" : ".dtors";
  if (Priority != 65535)
    raw_string_ostream(Name) << format(".%05u", 65535 - Priority);

  return Ctx.getAssociativeCOFFSection(
      Ctx.getCOFFSection(Name, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                                   COFF::IMAGE_SCN_MEM_READ |
                                   COFF::IMAGE_SCN_MEM_WRITE),
      KeySym, 0);
}

MCSection *TargetLoweringObjectFileCOFF::getStaticCtorSection(
    unsigned Priority, const MCSymbol *KeySym) const {
  return getCOFFStaticStructorSection(
      getContext(), getContext().getTargetTriple(), true, Priority, KeySym,
      static_cast<MCSectionCOFF *>(StaticCtorSection));
}

MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
    unsigned Priority, const MCSymbol *KeySym) const {
  return getCOFFStaticStructorSection(
      getContext(), getContext().getTargetTriple(), false, Priority, KeySym,
      static_cast<MCSectionCOFF *>(StaticDtorSection));
}

const MCExpr *TargetLoweringObjectFileCOFF::lowerRelativeReference(
    const GlobalValue *LHS, const GlobalValue *RHS, int64_t Addend,
    std::optional<int64_t> PCRelativeOffset, const TargetMachine &TM) const {
  const Triple &T = LHS->getParent()->getTargetTriple();
  if (T.isOSCygMing())
    return nullptr;

  // Our symbols should exist in address space zero, cowardly no-op if
  // otherwise.
  if (LHS->getType()->getPointerAddressSpace() != 0 ||
      RHS->getType()->getPointerAddressSpace() != 0)
    return nullptr;

  const auto *GA = dyn_cast<GlobalAlias>(LHS);
  const GlobalObject *GO = GA ? dyn_cast_or_null<GlobalObject>(GA->getAliasee())
                              : dyn_cast<GlobalObject>(LHS);

  // Both ptrtoint instructions must wrap global objects:
  // - Only global variables that are dso_local are eligible for image relative
  //   relocations.
  // - FIXME: Referring to a dllimport function produces an image-relative
  //   relocation against the local import thunk rather than the canonical
  //   function pointer, which lacks program-wide pointer identity. This is
  //   sufficient for use cases like MSVC exception handling metadata (where the
  //   function is only invoked), but is not theoretically sound in general.
  //   We probably need something like dso_local_equivalent to explicitly
  //   request a callable local entry point.
  // - The subtrahend refers to the special symbol __ImageBase, a
  //   GlobalVariable. We expect __ImageBase to be a global variable without a
  //   section, externally defined.
  //
  // It should look something like this: @__ImageBase = external constant i8
  if (!GO || (isa<GlobalVariable>(GO) && !TM.shouldAssumeDSOLocal(LHS)) ||
      GO->isThreadLocal() || !isa<GlobalVariable>(RHS) ||
      RHS->isThreadLocal() || RHS->getName() != "__ImageBase" ||
      !RHS->hasExternalLinkage() ||
      cast<GlobalVariable>(RHS)->hasInitializer() || RHS->hasSection())
    return nullptr;

  const MCExpr *Res = MCSymbolRefExpr::create(
      TM.getSymbol(LHS), MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
  if (Addend != 0)
    Res = MCBinaryExpr::createAdd(
        Res, MCConstantExpr::create(Addend, getContext()), getContext());
  return Res;
}

static std::string APIntToHexString(const APInt &AI) {
  unsigned Width = (AI.getBitWidth() / 8) * 2;
  std::string HexString = toString(AI, 16, /*Signed=*/false);
  llvm::transform(HexString, HexString.begin(), tolower);
  unsigned Size = HexString.size();
  assert(Width >= Size && "hex string is too large!");
  HexString.insert(HexString.begin(), Width - Size, '0');

  return HexString;
}

static std::string scalarConstantToHexString(const Constant *C) {
  Type *Ty = C->getType();
  if (isa<UndefValue>(C)) {
    return APIntToHexString(APInt::getZero(Ty->getPrimitiveSizeInBits()));
  } else if (const auto *CFP = dyn_cast<ConstantFP>(C)) {
    if (CFP->getType()->isFloatingPointTy())
      return APIntToHexString(CFP->getValueAPF().bitcastToAPInt());

    std::string HexString;
    unsigned NumElements =
        cast<FixedVectorType>(CFP->getType())->getNumElements();
    for (unsigned I = 0; I < NumElements; ++I)
      HexString += APIntToHexString(CFP->getValueAPF().bitcastToAPInt());
    return HexString;
  } else if (const auto *CI = dyn_cast<ConstantInt>(C)) {
    if (CI->getType()->isIntegerTy())
      return APIntToHexString(CI->getValue());

    std::string HexString;
    unsigned NumElements =
        cast<FixedVectorType>(CI->getType())->getNumElements();
    for (unsigned I = 0; I < NumElements; ++I)
      HexString += APIntToHexString(CI->getValue());
    return HexString;
  } else {
    unsigned NumElements;
    if (auto *VTy = dyn_cast<VectorType>(Ty))
      NumElements = cast<FixedVectorType>(VTy)->getNumElements();
    else
      NumElements = Ty->getArrayNumElements();
    std::string HexString;
    for (int I = NumElements - 1, E = -1; I != E; --I)
      HexString += scalarConstantToHexString(C->getAggregateElement(I));
    return HexString;
  }
}

MCSection *TargetLoweringObjectFileCOFF::getSectionForConstant(
    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
    const Function *F) const {
  if (Kind.isMergeableConst() && C &&
      getContext().getAsmInfo().hasCOFFComdatConstants()) {
    // This creates comdat sections with the given symbol name, but unless
    // AsmPrinter::GetCPISymbol actually makes the symbol global, the symbol
    // will be created with a null storage class, which makes GNU binutils
    // error out.
    const unsigned Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                                     COFF::IMAGE_SCN_MEM_READ |
                                     COFF::IMAGE_SCN_LNK_COMDAT;
    std::string COMDATSymName;
    if (Kind.isMergeableConst4()) {
      if (Alignment <= 4) {
        COMDATSymName = "__real@" + scalarConstantToHexString(C);
        Alignment = Align(4);
      }
    } else if (Kind.isMergeableConst8()) {
      if (Alignment <= 8) {
        COMDATSymName = "__real@" + scalarConstantToHexString(C);
        Alignment = Align(8);
      }
    } else if (Kind.isMergeableConst16()) {
      // FIXME: These may not be appropriate for non-x86 architectures.
      if (Alignment <= 16) {
        COMDATSymName = "__xmm@" + scalarConstantToHexString(C);
        Alignment = Align(16);
      }
    } else if (Kind.isMergeableConst32()) {
      if (Alignment <= 32) {
        COMDATSymName = "__ymm@" + scalarConstantToHexString(C);
        Alignment = Align(32);
      }
    }

    if (!COMDATSymName.empty())
      return getContext().getCOFFSection(".rdata", Characteristics,
                                         COMDATSymName,
                                         COFF::IMAGE_COMDAT_SELECT_ANY);
  }

  return TargetLoweringObjectFile::getSectionForConstant(DL, Kind, C, Alignment,
                                                         F);
}

//===----------------------------------------------------------------------===//
//                                  Wasm
//===----------------------------------------------------------------------===//

static const Comdat *getWasmComdat(const GlobalValue *GV) {
  const Comdat *C = GV->getComdat();
  if (!C)
    return nullptr;

  if (C->getSelectionKind() != Comdat::Any)
    report_fatal_error("WebAssembly COMDATs only support "
                       "SelectionKind::Any, '" + C->getName() + "' cannot be "
                       "lowered.");

  return C;
}

static unsigned getWasmSectionFlags(SectionKind K, bool Retain) {
  unsigned Flags = 0;

  if (K.isThreadLocal())
    Flags |= wasm::WASM_SEG_FLAG_TLS;

  if (K.isMergeableCString())
    Flags |= wasm::WASM_SEG_FLAG_STRINGS;

  if (Retain)
    Flags |= wasm::WASM_SEG_FLAG_RETAIN;

  // TODO(sbc): Add suport for K.isMergeableConst()

  return Flags;
}

void TargetLoweringObjectFileWasm::initialize(MCContext &Ctx,
                                              const TargetMachine &TM,
                                              const Module &M) {
  TargetLoweringObjectFile::initialize(Ctx, TM, M);

  SmallVector<GlobalValue *, 4> Vec;
  collectUsedGlobalVariables(M, Vec, false);
  for (GlobalValue *GV : Vec)
    if (auto *GO = dyn_cast<GlobalObject>(GV))
      Used.insert(GO);
}

MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  // We don't support explict section names for functions in the wasm object
  // format.  Each function has to be in its own unique section.
  if (isa<Function>(GO)) {
    return SelectSectionForGlobal(GO, Kind, TM);
  }

  StringRef Name = GO->getSection();

  // Certain data sections we treat as named custom sections rather than
  // segments within the data section.
  // This could be avoided if all data segements (the wasm sense) were
  // represented as their own sections (in the llvm sense).
  // TODO(sbc): https://github.com/WebAssembly/tool-conventions/issues/138
  if (Name == getInstrProfSectionName(IPSK_covmap, Triple::Wasm,
                                      /*AddSegmentInfo=*/false) ||
      Name == getInstrProfSectionName(IPSK_covfun, Triple::Wasm,
                                      /*AddSegmentInfo=*/false) ||
      Name == ".llvmbc" || Name == ".llvmcmd")
    Kind = SectionKind::getMetadata();

  StringRef Group = "";
  if (const Comdat *C = getWasmComdat(GO)) {
    Group = C->getName();
  }

  unsigned Flags = getWasmSectionFlags(Kind, Used.count(GO));
  MCSectionWasm *Section = getContext().getWasmSection(Name, Kind, Flags, Group,
                                                       MCSection::NonUniqueID);

  return Section;
}

static MCSectionWasm *
selectWasmSectionForGlobal(MCContext &Ctx, const GlobalObject *GO,
                           SectionKind Kind, Mangler &Mang,
                           const TargetMachine &TM, bool EmitUniqueSection,
                           unsigned *NextUniqueID, bool Retain) {
  StringRef Group = "";
  if (const Comdat *C = getWasmComdat(GO)) {
    Group = C->getName();
  }

  bool UniqueSectionNames = TM.getUniqueSectionNames();
  SmallString<128> Name = getSectionPrefixForGlobal(Kind, /*IsLarge=*/false);

  if (const auto *F = dyn_cast<Function>(GO)) {
    const auto &OptionalPrefix = F->getSectionPrefix();
    if (OptionalPrefix)
      raw_svector_ostream(Name) << '.' << *OptionalPrefix;
  }

  if (EmitUniqueSection && UniqueSectionNames) {
    Name.push_back('.');
    TM.getNameWithPrefix(Name, GO, Mang, true);
  }
  unsigned UniqueID = MCSection::NonUniqueID;
  if (EmitUniqueSection && !UniqueSectionNames) {
    UniqueID = *NextUniqueID;
    (*NextUniqueID)++;
  }

  unsigned Flags = getWasmSectionFlags(Kind, Retain);
  return Ctx.getWasmSection(Name, Kind, Flags, Group, UniqueID);
}

MCSection *TargetLoweringObjectFileWasm::SelectSectionForGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {

  if (Kind.isCommon())
    report_fatal_error("mergable sections not supported yet on wasm");

  // If we have -ffunction-section or -fdata-section then we should emit the
  // global value to a uniqued section specifically for it.
  bool EmitUniqueSection = false;
  if (Kind.isText())
    EmitUniqueSection = TM.getFunctionSections();
  else
    EmitUniqueSection = TM.getDataSections();
  EmitUniqueSection |= GO->hasComdat();
  bool Retain = Used.count(GO);
  EmitUniqueSection |= Retain;

  return selectWasmSectionForGlobal(getContext(), GO, Kind, getMangler(), TM,
                                    EmitUniqueSection, &NextUniqueID, Retain);
}

bool TargetLoweringObjectFileWasm::shouldPutJumpTableInFunctionSection(
    bool UsesLabelDifference, const Function &F) const {
  // We can always create relative relocations, so use another section
  // that can be marked non-executable.
  return false;
}

void TargetLoweringObjectFileWasm::InitializeWasm() {
  StaticCtorSection =
      getContext().getWasmSection(".init_array", SectionKind::getData());

  // We don't use PersonalityEncoding and LSDAEncoding because we don't emit
  // .cfi directives. We use TTypeEncoding to encode typeinfo global variables.
  TTypeEncoding = dwarf::DW_EH_PE_absptr;
}

MCSection *TargetLoweringObjectFileWasm::getStaticCtorSection(
    unsigned Priority, const MCSymbol *KeySym) const {
  return Priority == UINT16_MAX ?
         StaticCtorSection :
         getContext().getWasmSection(".init_array." + utostr(Priority),
                                     SectionKind::getData());
}

MCSection *TargetLoweringObjectFileWasm::getStaticDtorSection(
    unsigned Priority, const MCSymbol *KeySym) const {
  report_fatal_error("@llvm.global_dtors should have been lowered already");
}

//===----------------------------------------------------------------------===//
//                                  XCOFF
//===----------------------------------------------------------------------===//
bool TargetLoweringObjectFileXCOFF::ShouldEmitEHBlock(
    const MachineFunction *MF) {
  if (!MF->getLandingPads().empty())
    return true;

  const Function &F = MF->getFunction();
  if (!F.hasPersonalityFn() || !F.needsUnwindTableEntry())
    return false;

  const GlobalValue *Per =
      dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts());
  assert(Per && "Personality routine is not a GlobalValue type.");
  if (isNoOpWithoutInvoke(classifyEHPersonality(Per)))
    return false;

  return true;
}

bool TargetLoweringObjectFileXCOFF::ShouldSetSSPCanaryBitInTB(
    const MachineFunction *MF) {
  const Function &F = MF->getFunction();
  if (!F.hasStackProtectorFnAttr())
    return false;
  // FIXME: check presence of canary word
  // There are cases that the stack protectors are not really inserted even if
  // the attributes are on.
  return true;
}

MCSymbol *
TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(const MachineFunction *MF) {
  auto *EHInfoSym =
      static_cast<MCSymbolXCOFF *>(MF->getContext().getOrCreateSymbol(
          "__ehinfo." + Twine(MF->getFunctionNumber())));
  EHInfoSym->setEHInfo();
  return EHInfoSym;
}

MCSymbol *
TargetLoweringObjectFileXCOFF::getTargetSymbol(const GlobalValue *GV,
                                               const TargetMachine &TM) const {
  // We always use a qualname symbol for a GV that represents
  // a declaration, a function descriptor, or a common symbol. An IFunc is
  // lowered as a special trampoline function which has an entry point and a
  // descriptor.
  // If a GV represents a GlobalVariable and -fdata-sections is enabled, we
  // also return a qualname so that a label symbol could be avoided.
  // It is inherently ambiguous when the GO represents the address of a
  // function, as the GO could either represent a function descriptor or a
  // function entry point. We choose to always return a function descriptor
  // here.
  if (const GlobalObject *GO = dyn_cast<GlobalObject>(GV)) {
    if (GO->isDeclarationForLinker())
      return static_cast<const MCSectionXCOFF *>(
                 getSectionForExternalReference(GO, TM))
          ->getQualNameSymbol();

    if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
      if (GVar->hasAttribute("toc-data"))
        return static_cast<const MCSectionXCOFF *>(
                   SectionForGlobal(GVar, SectionKind::getData(), TM))
            ->getQualNameSymbol();

    if (isa<GlobalIFunc>(GO))
      return static_cast<const MCSectionXCOFF *>(
                 getSectionForFunctionDescriptor(GO, TM))
          ->getQualNameSymbol();

    SectionKind GOKind = getKindForGlobal(GO, TM);
    if (GOKind.isText())
      return static_cast<const MCSectionXCOFF *>(
                 getSectionForFunctionDescriptor(cast<Function>(GO), TM))
          ->getQualNameSymbol();
    if ((TM.getDataSections() && !GO->hasSection()) || GO->hasCommonLinkage() ||
        GOKind.isBSSLocal() || GOKind.isThreadBSSLocal())
      return static_cast<const MCSectionXCOFF *>(
                 SectionForGlobal(GO, GOKind, TM))
          ->getQualNameSymbol();
  }

  // For all other cases, fall back to getSymbol to return the unqualified name.
  return nullptr;
}

MCSection *TargetLoweringObjectFileXCOFF::getExplicitSectionGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  if (!GO->hasSection())
    report_fatal_error("#pragma clang section is not yet supported");

  StringRef SectionName = GO->getSection();

  // Handle the XCOFF::TD case first, then deal with the rest.
  if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO))
    if (GVar->hasAttribute("toc-data"))
      return getContext().getXCOFFSection(
          SectionName, Kind,
          XCOFF::CsectProperties(/*MappingClass*/ XCOFF::XMC_TD, XCOFF::XTY_SD),
          /* MultiSymbolsAllowed*/ true);

  XCOFF::StorageMappingClass MappingClass;
  if (Kind.isText())
    MappingClass = XCOFF::XMC_PR;
  else if (Kind.isData() || Kind.isBSS())
    MappingClass = XCOFF::XMC_RW;
  else if (Kind.isReadOnlyWithRel())
    MappingClass =
        TM.Options.XCOFFReadOnlyPointers ? XCOFF::XMC_RO : XCOFF::XMC_RW;
  else if (Kind.isReadOnly())
    MappingClass = XCOFF::XMC_RO;
  else
    report_fatal_error("XCOFF other section types not yet implemented.");

  return getContext().getXCOFFSection(
      SectionName, Kind, XCOFF::CsectProperties(MappingClass, XCOFF::XTY_SD),
      /* MultiSymbolsAllowed*/ true);
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForExternalReference(
    const GlobalObject *GO, const TargetMachine &TM) const {
  assert(GO->isDeclarationForLinker() &&
         "Tried to get ER section for a defined global.");

  SmallString<128> Name;
  getNameWithPrefix(Name, GO, TM);

  // AIX TLS local-dynamic does not need the external reference for the
  // "_$TLSML" symbol.
  if (GO->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&
      GO->hasName() && GO->getName() == "_$TLSML") {
    return getContext().getXCOFFSection(
        Name, SectionKind::getData(),
        XCOFF::CsectProperties(XCOFF::XMC_TC, XCOFF::XTY_SD));
  }

  XCOFF::StorageMappingClass SMC =
      isa<Function>(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA;
  if (GO->isThreadLocal())
    SMC = XCOFF::XMC_UL;

  if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO))
    if (GVar->hasAttribute("toc-data"))
      SMC = XCOFF::XMC_TD;

  // Externals go into a csect of type ER.
  return getContext().getXCOFFSection(
      Name, SectionKind::getMetadata(),
      XCOFF::CsectProperties(SMC, XCOFF::XTY_ER));
}

MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  // Handle the XCOFF::TD case first, then deal with the rest.
  if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO))
    if (GVar->hasAttribute("toc-data")) {
      SmallString<128> Name;
      getNameWithPrefix(Name, GO, TM);
      XCOFF::SymbolType symType =
          GO->hasCommonLinkage() ? XCOFF::XTY_CM : XCOFF::XTY_SD;
      return getContext().getXCOFFSection(
          Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_TD, symType),
          /* MultiSymbolsAllowed*/ true);
    }

  // Common symbols go into a csect with matching name which will get mapped
  // into the .bss section.
  // Zero-initialized local TLS symbols go into a csect with matching name which
  // will get mapped into the .tbss section.
  if (Kind.isBSSLocal() || GO->hasCommonLinkage() || Kind.isThreadBSSLocal()) {
    SmallString<128> Name;
    getNameWithPrefix(Name, GO, TM);
    XCOFF::StorageMappingClass SMC = Kind.isBSSLocal() ? XCOFF::XMC_BS
                                     : Kind.isCommon() ? XCOFF::XMC_RW
                                                       : XCOFF::XMC_UL;
    return getContext().getXCOFFSection(
        Name, Kind, XCOFF::CsectProperties(SMC, XCOFF::XTY_CM));
  }

  if (Kind.isText()) {
    if (TM.getFunctionSections()) {
      return static_cast<const MCSymbolXCOFF *>(
                 getFunctionEntryPointSymbol(GO, TM))
          ->getRepresentedCsect();
    }
    return TextSection;
  }

  if (TM.Options.XCOFFReadOnlyPointers && Kind.isReadOnlyWithRel()) {
    if (!TM.getDataSections())
      report_fatal_error(
          "ReadOnlyPointers is supported only if data sections is turned on");

    SmallString<128> Name;
    getNameWithPrefix(Name, GO, TM);
    return getContext().getXCOFFSection(
        Name, SectionKind::getReadOnly(),
        XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD));
  }

  // For BSS kind, zero initialized data must be emitted to the .data section
  // because external linkage control sections that get mapped to the .bss
  // section will be linked as tentative definitions, which is only appropriate
  // for SectionKind::Common.
  if (Kind.isData() || Kind.isReadOnlyWithRel() || Kind.isBSS()) {
    if (TM.getDataSections()) {
      SmallString<128> Name;
      getNameWithPrefix(Name, GO, TM);
      return getContext().getXCOFFSection(
          Name, SectionKind::getData(),
          XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD));
    }
    return DataSection;
  }

  if (Kind.isReadOnly()) {
    if (TM.getDataSections()) {
      SmallString<128> Name;
      getNameWithPrefix(Name, GO, TM);
      return getContext().getXCOFFSection(
          Name, SectionKind::getReadOnly(),
          XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD));
    }
    return ReadOnlySection;
  }

  // External/weak TLS data and initialized local TLS data are not eligible
  // to be put into common csect. If data sections are enabled, thread
  // data are emitted into separate sections. Otherwise, thread data
  // are emitted into the .tdata section.
  if (Kind.isThreadLocal()) {
    if (TM.getDataSections()) {
      SmallString<128> Name;
      getNameWithPrefix(Name, GO, TM);
      return getContext().getXCOFFSection(
          Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_TL, XCOFF::XTY_SD));
    }
    return TLSDataSection;
  }

  report_fatal_error("XCOFF other section types not yet implemented.");
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForJumpTable(
    const Function &F, const TargetMachine &TM) const {
  assert (!F.getComdat() && "Comdat not supported on XCOFF.");

  if (!TM.getFunctionSections())
    return ReadOnlySection;

  // If the function can be removed, produce a unique section so that
  // the table doesn't prevent the removal.
  SmallString<128> NameStr(".rodata.jmp..");
  getNameWithPrefix(NameStr, &F, TM);
  return getContext().getXCOFFSection(
      NameStr, SectionKind::getReadOnly(),
      XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD));
}

bool TargetLoweringObjectFileXCOFF::shouldPutJumpTableInFunctionSection(
    bool UsesLabelDifference, const Function &F) const {
  return false;
}

/// Given a mergeable constant with the specified size and relocation
/// information, return a section that it should be placed in.
MCSection *TargetLoweringObjectFileXCOFF::getSectionForConstant(
    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
    const Function *F) const {
  // TODO: Enable emiting constant pool to unique sections when we support it.
  if (Alignment > Align(16))
    report_fatal_error("Alignments greater than 16 not yet supported.");

  if (Alignment == Align(8)) {
    assert(ReadOnly8Section && "Section should always be initialized.");
    return ReadOnly8Section;
  }

  if (Alignment == Align(16)) {
    assert(ReadOnly16Section && "Section should always be initialized.");
    return ReadOnly16Section;
  }

  return ReadOnlySection;
}

void TargetLoweringObjectFileXCOFF::initialize(MCContext &Ctx,
                                               const TargetMachine &TgtM,
                                               const Module &M) {
  TargetLoweringObjectFile::initialize(Ctx, TgtM, M);
  TTypeEncoding =
      dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_datarel |
      (TgtM.getTargetTriple().isArch32Bit() ? dwarf::DW_EH_PE_sdata4
                                            : dwarf::DW_EH_PE_sdata8);
  PersonalityEncoding = 0;
  LSDAEncoding = 0;
  CallSiteEncoding = dwarf::DW_EH_PE_udata4;

  // AIX debug for thread local location is not ready. And for integrated as
  // mode, the relocatable address for the thread local variable will cause
  // linker error. So disable the location attribute generation for thread local
  // variables for now.
  // FIXME: when TLS debug on AIX is ready, remove this setting.
  SupportDebugThreadLocalLocation = false;
}

MCSection *TargetLoweringObjectFileXCOFF::getStaticCtorSection(
	unsigned Priority, const MCSymbol *KeySym) const {
  report_fatal_error("no static constructor section on AIX");
}

MCSection *TargetLoweringObjectFileXCOFF::getStaticDtorSection(
	unsigned Priority, const MCSymbol *KeySym) const {
  report_fatal_error("no static destructor section on AIX");
}

XCOFF::StorageClass
TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(const GlobalValue *GV) {
  assert(!isa<GlobalIFunc>(GV) && "GlobalIFunc is not supported on AIX.");

  switch (GV->getLinkage()) {
  case GlobalValue::InternalLinkage:
  case GlobalValue::PrivateLinkage:
    return XCOFF::C_HIDEXT;
  case GlobalValue::ExternalLinkage:
  case GlobalValue::CommonLinkage:
  case GlobalValue::AvailableExternallyLinkage:
    return XCOFF::C_EXT;
  case GlobalValue::ExternalWeakLinkage:
  case GlobalValue::LinkOnceAnyLinkage:
  case GlobalValue::LinkOnceODRLinkage:
  case GlobalValue::WeakAnyLinkage:
  case GlobalValue::WeakODRLinkage:
    return XCOFF::C_WEAKEXT;
  case GlobalValue::AppendingLinkage:
    report_fatal_error(
        "There is no mapping that implements AppendingLinkage for XCOFF.");
  }
  llvm_unreachable("Unknown linkage type!");
}

MCSymbol *TargetLoweringObjectFileXCOFF::getFunctionEntryPointSymbol(
    const GlobalValue *Func, const TargetMachine &TM) const {
  assert((isa<Function>(Func) || isa<GlobalIFunc>(Func) ||
          (isa<GlobalAlias>(Func) &&
           isa_and_nonnull<Function>(
               cast<GlobalAlias>(Func)->getAliaseeObject()))) &&
         "Func must be a function or an alias which has a function as base "
         "object.");

  SmallString<128> NameStr;
  NameStr.push_back('.');
  getNameWithPrefix(NameStr, Func, TM);

  // When -function-sections is enabled and explicit section is not specified,
  // it's not necessary to emit function entry point label any more. We will use
  // function entry point csect instead. And for function delcarations, the
  // undefined symbols gets treated as csect with XTY_ER property.
  if (((TM.getFunctionSections() && !Func->hasSection()) ||
       Func->isDeclarationForLinker()) &&
      (isa<Function>(Func) || isa<GlobalIFunc>(Func))) {
    return getContext()
        .getXCOFFSection(
            NameStr, SectionKind::getText(),
            XCOFF::CsectProperties(XCOFF::XMC_PR, Func->isDeclarationForLinker()
                                                      ? XCOFF::XTY_ER
                                                      : XCOFF::XTY_SD))
        ->getQualNameSymbol();
  }

  return getContext().getOrCreateSymbol(NameStr);
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForFunctionDescriptor(
    const GlobalObject *F, const TargetMachine &TM) const {
  assert((isa<Function>(F) || isa<GlobalIFunc>(F)) &&
         "F must be a function or ifunc object.");
  SmallString<128> NameStr;
  getNameWithPrefix(NameStr, F, TM);
  return getContext().getXCOFFSection(
      NameStr, SectionKind::getData(),
      XCOFF::CsectProperties(XCOFF::XMC_DS, XCOFF::XTY_SD));
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForTOCEntry(
    const MCSymbol *Sym, const TargetMachine &TM) const {
  const XCOFF::StorageMappingClass SMC = [](const MCSymbol *Sym,
                                            const TargetMachine &TM) {
    auto *XSym = static_cast<const MCSymbolXCOFF *>(Sym);

    // The "_$TLSML" symbol for TLS local-dynamic mode requires XMC_TC,
    // otherwise the AIX assembler will complain.
    if (XSym->getSymbolTableName() == "_$TLSML")
      return XCOFF::XMC_TC;

    // Use large code model toc entries for ehinfo symbols as they are
    // never referenced directly. The runtime loads their TOC entry
    // addresses from the trace-back table.
    if (XSym->isEHInfo())
      return XCOFF::XMC_TE;

    // If the symbol does not have a code model specified use the module value.
    if (!XSym->hasPerSymbolCodeModel())
      return TM.getCodeModel() == CodeModel::Large ? XCOFF::XMC_TE
                                                   : XCOFF::XMC_TC;

    return XSym->getPerSymbolCodeModel() == MCSymbolXCOFF::CM_Large
               ? XCOFF::XMC_TE
               : XCOFF::XMC_TC;
  }(Sym, TM);

  return getContext().getXCOFFSection(
      static_cast<const MCSymbolXCOFF *>(Sym)->getSymbolTableName(),
      SectionKind::getData(), XCOFF::CsectProperties(SMC, XCOFF::XTY_SD));
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForLSDA(
    const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
  auto *LSDA = static_cast<MCSectionXCOFF *>(LSDASection);
  if (TM.getFunctionSections()) {
    // If option -ffunction-sections is on, append the function name to the
    // name of the LSDA csect so that each function has its own LSDA csect.
    // This helps the linker to garbage-collect EH info of unused functions.
    SmallString<128> NameStr = LSDA->getName();
    raw_svector_ostream(NameStr) << '.' << F.getName();
    LSDA = getContext().getXCOFFSection(NameStr, LSDA->getKind(),
                                        LSDA->getCsectProp());
  }
  return LSDA;
}
//===----------------------------------------------------------------------===//
//                                  GOFF
//===----------------------------------------------------------------------===//
TargetLoweringObjectFileGOFF::TargetLoweringObjectFileGOFF() = default;

void TargetLoweringObjectFileGOFF::initialize(MCContext &Ctx,
                                              const TargetMachine &TM,
                                              const Module &M) {
  TargetLoweringObjectFile::initialize(Ctx, TM, M);

  // Construct the default names for the root SD and the ADA PR symbol.
  StringRef FileName = sys::path::stem(M.getSourceFileName());
  if (FileName.size() > 1 && FileName.starts_with('<') &&
      FileName.ends_with('>'))
    FileName = FileName.substr(1, FileName.size() - 2);
  DefaultRootSDName = Twine(FileName).concat("#C").str();
  DefaultADAPRName = Twine(FileName).concat("#S").str();
  MCSectionGOFF *RootSD =
      static_cast<MCSectionGOFF *>(TextSection)->getParent();
  MCSectionGOFF *ADAPR = static_cast<MCSectionGOFF *>(ADASection);
  RootSD->setName(DefaultRootSDName);
  ADAPR->setName(DefaultADAPRName);
  // Initialize the label for the text section.
  MCSymbolGOFF *TextLD = static_cast<MCSymbolGOFF *>(
      getContext().getOrCreateSymbol(RootSD->getName()));
  TextLD->setCodeData(GOFF::ESD_EXE_CODE);
  TextLD->setLinkage(GOFF::ESD_LT_XPLink);
  TextLD->setExternal(false);
  TextLD->setWeak(false);
  TextLD->setADA(ADAPR);
  TextSection->setBeginSymbol(TextLD);
  // Initialize the label for the ADA section.
  MCSymbolGOFF *ADASym = static_cast<MCSymbolGOFF *>(
      getContext().getOrCreateSymbol(ADAPR->getName()));
  ADAPR->setBeginSymbol(ADASym);
}

bool TargetLoweringObjectFileGOFF::shouldPutJumpTableInFunctionSection(
    bool UsesLabelDifference, const Function &F) const {
  return true;
}

MCSection *TargetLoweringObjectFileGOFF::getSectionForConstant(
    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
    const Function *F) const {
  return TextSection;
}

MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  return SelectSectionForGlobal(GO, Kind, TM);
}

MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
    const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
  std::string Name = "GCC_except." + F.getName().str();

  MCSectionGOFF *SD = getContext().getGOFFSection(
      SectionKind::getMetadata(), Name,
      GOFF::SDAttr{GOFF::ESD_TA_Unspecified, GOFF::ESD_BSC_Section});
  MCSectionGOFF *WSA = getContext().getGOFFSection(
      SectionKind::getMetadata(), GOFF::CLASS_WSA,
      GOFF::EDAttr{false, GOFF::ESD_RMODE_64, GOFF::ESD_NS_Parts,
                   GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
                   GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_0, 0},
      SD);
  WSA->setAlignment(Align(8));
  return getContext().getGOFFSection(
      SectionKind::getData(), Name,
      GOFF::PRAttr{false, GOFF::ESD_EXE_DATA, GOFF::ESD_BST_Strong,
                   GOFF::ESD_LT_XPLink, GOFF::ESD_BSC_Section, 0},
      WSA);
}

MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  auto *Symbol = TM.getSymbol(GO);

  // Read-only data stays in the code section only if it is local: references
  // from other translation units are always parts in the WSA.
  if (Kind.isBSS() || Kind.isData() || Kind.isReadOnlyWithRel() ||
      (Kind.isReadOnly() && !GO->hasLocalLinkage())) {
    GOFF::ESDBindingScope PRBindingScope =
        GO->hasExternalLinkage()
            ? (GO->hasDefaultVisibility() ? GOFF::ESD_BSC_ImportExport
                                          : GOFF::ESD_BSC_Library)
            : GOFF::ESD_BSC_Section;
    GOFF::ESDBindingScope SDBindingScope =
        PRBindingScope == GOFF::ESD_BSC_Section ? GOFF::ESD_BSC_Section
                                                : GOFF::ESD_BSC_Unspecified;
    MaybeAlign Alignment;
    if (auto *F = dyn_cast<Function>(GO))
      Alignment = F->getAlign();
    else if (auto *V = dyn_cast<GlobalVariable>(GO))
      Alignment = V->getAlign();
    MCSectionGOFF *SD = getContext().getGOFFSection(
        SectionKind::getMetadata(), Symbol->getName(),
        GOFF::SDAttr{GOFF::ESD_TA_Unspecified, SDBindingScope});
    MCSectionGOFF *ED = getContext().getGOFFSection(
        SectionKind::getMetadata(), GOFF::CLASS_WSA,
        GOFF::EDAttr{false, GOFF::ESD_RMODE_64, GOFF::ESD_NS_Parts,
                     GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
                     GOFF::ESD_LB_Deferred, GOFF::ESD_RQ_0, 0},
        SD);
    ED->setAlignment(Alignment.value_or(llvm::Align(8)));
    MCSectionGOFF *PR = getContext().getGOFFSection(
        Kind, Symbol->getName(),
        GOFF::PRAttr{false, GOFF::ESD_EXE_DATA, GOFF::ESD_BST_Strong,
                     GOFF::ESD_LT_XPLink, PRBindingScope, 0},
        ED);
    // The binder rejects zero-length PR sections. Mark the PR so the writer
    // inflates it to a valid length if needed.
    PR->setRequiresNonZeroLength();
    return PR;
  }
  return TextSection;
}

MCSection *
TargetLoweringObjectFileGOFF::getStaticXtorSection(unsigned Priority) const {
  // XL C/C++ compilers on z/OS support priorities from min-int to max-int, with
  // sinit as source priority 0. For clang, sinit has source priority 65535.
  // For GOFF, the priority sortkey field is an unsigned value. So, we
  // add min-int to get sorting to work properly but also subtract the
  // clang sinit (65535) value so internally xl sinit and clang sinit have
  // the same unsigned GOFF priority sortkey field value (i.e. 0x80000000).
  static constexpr const uint32_t ClangDefaultSinitPriority = 65535;
  uint32_t Prio = Priority + (0x80000000 - ClangDefaultSinitPriority);

  std::string Name(".xtor");
  if (Priority != ClangDefaultSinitPriority)
    Name = llvm::Twine(Name).concat(".").concat(llvm::utostr(Priority)).str();

  MCContext &Ctx = getContext();
  MCSectionGOFF *SInit = Ctx.getGOFFSection(
      SectionKind::getMetadata(), GOFF::CLASS_SINIT,
      GOFF::EDAttr{false, GOFF::ESD_RMODE_64, GOFF::ESD_NS_Parts,
                   GOFF::ESD_TS_ByteOriented, GOFF::ESD_BA_Merge,
                   GOFF::ESD_LB_Initial, GOFF::ESD_RQ_0,
                   GOFF::ESD_ALIGN_Doubleword},
      static_cast<const MCSectionGOFF *>(TextSection)->getParent());

  MCSectionGOFF *Xtor = Ctx.getGOFFSection(
      SectionKind::getData(), Name,
      GOFF::PRAttr{true, GOFF::ESD_EXE_DATA, GOFF::ESD_BST_Strong,
                   GOFF::ESD_LT_XPLink, GOFF::ESD_BSC_Section, Prio},
      SInit);
  return Xtor;
}
