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

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(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) {
  TargetLoweringObjectFile::Initialize(Ctx, TgtM);

  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 (Ctx.getAsmInfo().getExceptionHandlingType() == 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:
    if (isPositionIndependent()) {
      PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
        ((CM == CodeModel::Small || CM == CodeModel::Medium)
         ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
      LSDAEncoding = dwarf::DW_EH_PE_pcrel |
        (CM == CodeModel::Small
         ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
      TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
        ((CM == CodeModel::Small || CM == CodeModel::Medium)
         ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8);
    } else {
      PersonalityEncoding =
        (CM == CodeModel::Small || CM == CodeModel::Medium)
        ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr;
      LSDAEncoding = (CM == CodeModel::Small)
        ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr;
      TTypeEncoding = (CM == 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;
  }
}

void TargetLoweringObjectFileELF::getModuleMetadata(Module &M) {
  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,
                                                     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,
                                                       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;
  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) {
      if (JTE->Hotness == MachineFunctionDataHotness::Hot) {
        raw_svector_ostream(Name) << ".hot";
      } else {
        assert(JTE->Hotness == MachineFunctionDataHotness::Cold &&
               "Hotness must be cold");
        raw_svector_ostream(Name) << ".unlikely";
      }
      HasPrefix = true;
    } else if (std::optional<StringRef> Prefix = F->getSectionPrefix()) {
      raw_svector_ostream(Name) << '.' << *Prefix;
      HasPrefix = true;
    }
  } else if (const auto *GV = dyn_cast<GlobalVariable>(GO)) {
    if (std::optional<StringRef> Prefix = GV->getSectionPrefix()) {
      raw_svector_ostream(Name) << '.' << *Prefix;
      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 StringRef handlePragmaClangSection(const GlobalObject *GO,
                                          SectionKind Kind) {
  // Check if '#pragma clang section' name is applicable.
  // Note that pragma directive overrides -ffunction-section, -fdata-section
  // and so section name is exactly as user specified and not uniqued.
  const GlobalVariable *GV = dyn_cast<GlobalVariable>(GO);
  if (GV && GV->hasImplicitSection()) {
    auto Attrs = GV->getAttributes();
    if (Attrs.hasAttribute("bss-section") && Kind.isBSS())
      return Attrs.getAttribute("bss-section").getValueAsString();
    else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly())
      return Attrs.getAttribute("rodata-section").getValueAsString();
    else if (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel())
      return Attrs.getAttribute("relro-section").getValueAsString();
    else if (Attrs.hasAttribute("data-section") && Kind.isData())
      return Attrs.getAttribute("data-section").getValueAsString();
  }

  return GO->getSection();
}

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

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

  unsigned Flags = getELFSectionFlags(Kind, TM.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, TM.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, TM.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.
MCSection *TargetLoweringObjectFileELF::getSectionForConstant(
    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
    const Function *F) const {
  if (Kind.isMergeableConst4() && MergeableConst4Section)
    return MergeableConst4Section;
  if (Kind.isMergeableConst8() && MergeableConst8Section)
    return MergeableConst8Section;
  if (Kind.isMergeableConst16() && MergeableConst16Section)
    return MergeableConst16Section;
  if (Kind.isMergeableConst32() && MergeableConst32Section)
    return MergeableConst32Section;
  if (Kind.isReadOnly())
    return ReadOnlySection;

  assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
  return DataRelROSection;
}

MCSection *TargetLoweringObjectFileELF::getSectionForConstant(
    const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
    const Function *F, StringRef SectionSuffix) const {
  // TODO: Share code between this function and
  // MCObjectInfo::initELFMCObjectFileInfo.
  if (SectionSuffix.empty())
    return getSectionForConstant(DL, Kind, C, Alignment, F);

  auto &Context = getContext();
  StringRef CstPrefix = ".rodata";
  unsigned MergeableCstFlags = ELF::SHF_ALLOC | ELF::SHF_MERGE;
  if (TM->getCodeModel() == CodeModel::Large &&
      TM->getTargetTriple().getArch() == Triple::x86_64) {
    MergeableCstFlags |= ELF::SHF_X86_64_LARGE;
    CstPrefix = ".lrodata";
  }

  if (Kind.isMergeableConst4() && MergeableConst4Section)
    return Context.getELFSection(CstPrefix + ".cst4." + SectionSuffix + ".",
                                 ELF::SHT_PROGBITS, MergeableCstFlags, 4);
  if (Kind.isMergeableConst8() && MergeableConst8Section)
    return Context.getELFSection(CstPrefix + ".cst8." + SectionSuffix + ".",
                                 ELF::SHT_PROGBITS, MergeableCstFlags, 8);
  if (Kind.isMergeableConst16() && MergeableConst16Section)
    return Context.getELFSection(CstPrefix + ".cst16." + SectionSuffix + ".",
                                 ELF::SHT_PROGBITS, MergeableCstFlags, 16);
  if (Kind.isMergeableConst32() && MergeableConst32Section)
    return Context.getELFSection(CstPrefix + ".cst32." + SectionSuffix + ".",
                                 ELF::SHT_PROGBITS, MergeableCstFlags, 32);
  if (Kind.isReadOnly())
    return Context.getELFSection(".rodata." + SectionSuffix + ".",
                                 ELF::SHT_PROGBITS, ELF::SHF_ALLOC);

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

/// 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 = ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
  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) {
  TargetLoweringObjectFile::Initialize(Ctx, TM);
  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,
                                                       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,
                                                         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 = handlePragmaClangSection(GO, Kind);

  // 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 = handlePragmaClangSection(GO, Kind);
  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,
                                                      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, 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) {
  TargetLoweringObjectFile::Initialize(Ctx, TM);
  this->TM = &TM;
  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 = TM.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;

  // Both ptrtoint instructions must wrap global objects:
  // - Only global variables are eligible for image relative relocations.
  // - 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 (!isa<GlobalObject>(LHS) || !isa<GlobalVariable>(RHS) ||
      LHS->isThreadLocal() || 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::getModuleMetadata(Module &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) {
  TargetLoweringObjectFile::Initialize(Ctx, TgtM);
  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::getModuleMetadata(Module &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::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_exception_table." + F.getName().str();

  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_Initial, GOFF::ESD_RQ_0,
                   GOFF::ESD_ALIGN_Fullword, 0},
      static_cast<MCSectionGOFF *>(TextSection)->getParent());
  return getContext().getGOFFSection(SectionKind::getData(), Name,
                                     GOFF::PRAttr{true, GOFF::ESD_EXE_DATA,
                                                  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);

  if (Kind.isBSS() || Kind.isData()) {
    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();
    GOFF::ESDAlignment Align =
        Alignment ? static_cast<GOFF::ESDAlignment>(Log2(*Alignment))
                  : GOFF::ESD_ALIGN_Doubleword;
    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, Align, 0},
        SD);
    return getContext().getGOFFSection(Kind, Symbol->getName(),
                                       GOFF::PRAttr{false, GOFF::ESD_EXE_DATA,
                                                    GOFF::ESD_LT_XPLink,
                                                    PRBindingScope, 0},
                                       ED);
  }
  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_LT_XPLink,
                   GOFF::ESD_BSC_Section, Prio},
      SInit);
  return Xtor;
}
