//===- 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/ADT/Triple.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.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/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/PseudoProbe.h"
#include "llvm/IR/Type.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.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/MCValue.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <cassert>
#include <string>

using namespace llvm;
using namespace dwarf;

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

TargetLoweringObjectFileELF::TargetLoweringObjectFileELF() {
  SupportDSOLocalEquivalentLowering = true;
}

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
    LLVM_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.
    if (isPositionIndependent()) {
      // ILP32 uses sdata4 instead of sdata8
      if (TgtM.getTargetTriple().getEnvironment() == Triple::GNUILP32) {
        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_indirect | dwarf::DW_EH_PE_pcrel |
                              dwarf::DW_EH_PE_sdata8;
        LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8;
        TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
                        dwarf::DW_EH_PE_sdata8;
      }
    } else {
      PersonalityEncoding = dwarf::DW_EH_PE_absptr;
      LSDAEncoding = dwarf::DW_EH_PE_absptr;
      TTypeEncoding = dwarf::DW_EH_PE_absptr;
    }
    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;
    // We don't support PC-relative LSDA references in GAS so we use the default
    // DW_EH_PE_absptr for those.

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

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

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

  if (NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName)) {
    // Emit a descriptor for every function including functions that have an
    // available external linkage. We may not want this for imported functions
    // that has code in another thinLTO module but we don't have a good way to
    // tell them apart from inline functions defined in header files. Therefore
    // we put each descriptor in a separate comdat section and rely on the
    // linker to deduplicate.
    for (const auto *Operand : FuncInfo->operands()) {
      const auto *MD = cast<MDNode>(Operand);
      auto *GUID = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0));
      auto *Hash = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
      auto *Name = cast<MDString>(MD->getOperand(2));
      auto *S = C.getObjectFileInfo()->getPseudoProbeDescSection(
          TM->getFunctionSections() ? Name->getString() : StringRef());

      Streamer.switchSection(S);
      Streamer.emitInt64(GUID->getZExtValue());
      Streamer.emitInt64(Hash->getZExtValue());
      Streamer.emitULEB128IntValue(Name->getString().size());
      Streamer.emitBytes(Name->getString());
    }
  }

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

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 {
  SmallString<64> NameData("DW.ref.");
  NameData += Sym->getName();
  MCSymbolELF *Label =
      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).value());
  Streamer.emitSymbolAttribute(Label, MCSA_ELF_TypeObject);
  const MCExpr *E = MCConstantExpr::create(Size, getContext());
  Streamer.emitELFSize(Label, E);
  Streamer.emitLabel(Label);

  Streamer.emitSymbolValue(Sym, Size);
}

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 == ".llvmbc" || Name == ".llvmcmd")
    return SectionKind::getMetadata();

  if (Name.empty() || Name[0] != '.') return K;

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

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

  if (Name == ".tbss" ||
      Name.startswith(".tbss.") ||
      Name.startswith(".gnu.linkonce.tb.") ||
      Name.startswith(".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.startswith(".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 (K.isBSS() || K.isThreadBSS())
    return ELF::SHT_NOBITS;

  return ELF::SHT_PROGBITS;
}

static unsigned getELFSectionFlags(SectionKind K) {
  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())
    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;

  const MDOperand &Op = MD->getOperand(0);
  if (!Op.get())
    return nullptr;

  auto *VM = dyn_cast<ValueAsMetadata>(Op);
  if (!VM)
    report_fatal_error("MD_associated operand is not ValueAsMetadata");

  auto *OtherGV = dyn_cast<GlobalValue>(VM->getValue());
  return OtherGV ? dyn_cast<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) {
  if (Kind.isText())
    return ".text";
  if (Kind.isReadOnly())
    return ".rodata";
  if (Kind.isBSS())
    return ".bss";
  if (Kind.isThreadData())
    return ".tdata";
  if (Kind.isThreadBSS())
    return ".tbss";
  if (Kind.isData())
    return ".data";
  if (Kind.isReadOnlyWithRel())
    return ".data.rel.ro";
  llvm_unreachable("Unknown section kind");
}

static SmallString<128>
getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
                           Mangler &Mang, const TargetMachine &TM,
                           unsigned EntrySize, bool UniqueSectionName) {
  SmallString<128> Name;
  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->getParent()->getDataLayout().getPreferredAlign(
        cast<GlobalVariable>(GO));

    std::string SizeSpec = ".rodata.str" + utostr(EntrySize) + ".";
    Name = SizeSpec + utostr(Alignment.value());
  } else if (Kind.isMergeableConst()) {
    Name = ".rodata.cst";
    Name += utostr(EntrySize);
  } else {
    Name = getSectionPrefixForGlobal(Kind);
  }

  bool HasPrefix = false;
  if (const auto *F = dyn_cast<Function>(GO)) {
    if (Optional<StringRef> Prefix = F->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,
                         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 avalible until bintuils 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 MCContext::GenericSectionID;
  }

  const bool SymbolMergeable = Flags & ELF::SHF_MERGE;
  const bool SeenSectionNameBefore =
      Ctx.isELFGenericMergeableSection(SectionName);
  // If this is the first ocurrence of this section name, treat it as the
  // generic section
  if (!SymbolMergeable && !SeenSectionNameBefore)
    return MCContext::GenericSectionID;

  // 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)
    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, EntrySize, false);
  if (SymbolMergeable &&
      Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) &&
      SectionName.startswith(ImplicitSectionNameStem))
    return MCContext::GenericSectionID;

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

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

  // 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()) {
      SectionName = Attrs.getAttribute("bss-section").getValueAsString();
    } else if (Attrs.hasAttribute("rodata-section") && Kind.isReadOnly()) {
      SectionName = Attrs.getAttribute("rodata-section").getValueAsString();
    } else if (Attrs.hasAttribute("relro-section") && Kind.isReadOnlyWithRel()) {
      SectionName = Attrs.getAttribute("relro-section").getValueAsString();
    } else if (Attrs.hasAttribute("data-section") && Kind.isData()) {
      SectionName = Attrs.getAttribute("data-section").getValueAsString();
    }
  }
  const Function *F = dyn_cast<Function>(GO);
  if (F && F->hasFnAttribute("implicit-section-name")) {
    SectionName = F->getFnAttribute("implicit-section-name").getValueAsString();
  }

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

  StringRef Group = "";
  bool IsComdat = false;
  unsigned Flags = getELFSectionFlags(Kind);
  if (const Comdat *C = getELFComdat(GO)) {
    Group = C->getName();
    IsComdat = C->getSelectionKind() == Comdat::Any;
    Flags |= ELF::SHF_GROUP;
  }

  unsigned EntrySize = getEntrySizeForKind(Kind);
  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, getELFSectionType(SectionName, Kind), 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) {

  StringRef Group = "";
  bool IsComdat = false;
  if (const Comdat *C = getELFComdat(GO)) {
    Flags |= ELF::SHF_GROUP;
    Group = C->getName();
    IsComdat = C->getSelectionKind() == Comdat::Any;
  }

  // Get the section entry size based on the kind.
  unsigned EntrySize = getEntrySizeForKind(Kind);

  bool UniqueSectionName = false;
  unsigned UniqueID = MCContext::GenericSectionID;
  if (EmitUniqueSection) {
    if (TM.getUniqueSectionNames()) {
      UniqueSectionName = true;
    } else {
      UniqueID = *NextUniqueID;
      (*NextUniqueID)++;
    }
  }
  SmallString<128> Name = getELFSectionNameForGlobal(
      GO, Kind, Mang, TM, EntrySize, UniqueSectionName);

  // Use 0 as the unique ID for execute-only text.
  if (Kind.isExecuteOnly())
    UniqueID = 0;
  return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), 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;
    }
  }

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

  // 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);
  // If the function's section names is pre-determined via pragma or a
  // section attribute, call selectExplicitSectionGlobal.
  if (F.hasSection() || F.hasFnAttribute("implicit-section-name"))
    return selectExplicitSectionGlobal(
        &F, Kind, TM, getContext(), getMangler(), NextUniqueID,
        Used.count(&F), /* ForceUnique = */true);
  else
    return selectELFSectionForGlobal(
        getContext(), &F, Kind, getMangler(), TM, Used.count(&F),
        /*EmitUniqueSection=*/true, Flags, &NextUniqueID);
}

MCSection *TargetLoweringObjectFileELF::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;

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

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 = cast<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 = cast<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 {
  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;
}

/// 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 = MCContext::GenericSectionID;

  // 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;
  if (MBB.getSectionID() == MBBSectionID::ColdSectionID) {
    Name += BBSectionsColdTextPrefix;
    Name += MBB.getParent()->getName();
  } else if (MBB.getSectionID() == MBBSectionID::ExceptionSectionID) {
    Name += ".text.eh.";
    Name += MBB.getParent()->getName();
  } else {
    Name += MBB.getParent()->getSection()->getName();
    if (TM.getUniqueBasicBlockSectionNames()) {
      if (!Name.endswith("."))
        Name += ".";
      Name += MBB.getSymbol()->getName();
    } else {
      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::lowerRelativeReference(
    const GlobalValue *LHS, const GlobalValue *RHS,
    const TargetMachine &TM) const {
  // We may only use a PLT-relative relocation to refer to unnamed_addr
  // functions.
  if (!LHS->hasGlobalUnnamedAddr() || !LHS->getValueType()->isFunctionTy())
    return nullptr;

  // Basic correctness checks.
  if (LHS->getType()->getPointerAddressSpace() != 0 ||
      RHS->getType()->getPointerAddressSpace() != 0 || LHS->isThreadLocal() ||
      RHS->isThreadLocal())
    return nullptr;

  return MCBinaryExpr::createSub(
      MCSymbolRefExpr::create(TM.getSymbol(LHS), PLTRelativeVariantKind,
                              getContext()),
      MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext());
}

const MCExpr *TargetLoweringObjectFileELF::lowerDSOLocalEquivalent(
    const DSOLocalEquivalent *Equiv, const TargetMachine &TM) const {
  assert(supportDSOLocalEquivalentLowering());

  const auto *GV = Equiv->getGlobalValue();

  // A PLT entry is not needed for dso_local globals.
  if (GV->isDSOLocal() || GV->isImplicitDSOLocal())
    return MCSymbolRefExpr::create(TM.getSymbol(GV), getContext());

  return MCSymbolRefExpr::create(TM.getSymbol(GV), PLTRelativeVariantKind,
                                 getContext());
}

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 {
  // TODO(yln): Remove -lower-global-dtors-via-cxa-atexit fallback flag
  // (LowerGlobalDtorsViaCxaAtExit) and always issue a fatal error here.
  if (TM->Options.LowerGlobalDtorsViaCxaAtExit)
    report_fatal_error("@llvm.global_dtors should have been lowered already");
  return StaticDtorSection;
}

void TargetLoweringObjectFileMachO::emitModuleMetadata(MCStreamer &Streamer,
                                                       Module &M) const {
  // Emit the linker options if present.
  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);
    }
  }

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

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 = GO->getSection();

  const Function *F = dyn_cast<Function>(GO);
  if (F && F->hasFnAttribute("implicit-section-name")) {
    SectionName = F->getFnAttribute("implicit-section-name").getValueAsString();
  }

  // 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->getParent()->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->getParent()->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 {
  // 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
}

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.getSymB()->getSymbol();

  // 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().getPrivateGlobalPrefix();
  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, MCSymbolRefExpr::VK_None, Ctx);
  const MCExpr *LHS =
    MCSymbolRefExpr::create(Stub, MCSymbolRefExpr::VK_None, 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 (!AsmInfo.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 {
  int Selection = 0;
  unsigned Characteristics = getCOFFSectionFlags(Kind, TM);
  StringRef Name = GO->getSection();
  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, Kind, 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 = MCContext::GenericSectionID;
    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 (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().isWindowsGNUEnvironment())
        raw_svector_ostream(Name) << '$' << ComdatGV->getName();

      return getContext().getCOFFSection(Name, Characteristics, Kind,
                                         COMDATSymName, Selection, UniqueID);
    } else {
      SmallString<256> TmpData;
      getMangler().getNameWithPrefix(TmpData, GO, /*CannotUsePrivateLabel=*/true);
      return getContext().getCOFFSection(Name, Characteristics, Kind, 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, Kind, COMDATSymName,
      COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
}

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,
                               SectionKind::getReadOnly());
    Streamer.switchSection(S);
    Streamer.emitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO")));
    Streamer.emitInt32(Version);
    Streamer.emitInt32(Flags);
    Streamer.addBlankLine();
  }

  emitCGProfileMetadata(Streamer, M);
}

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());
    OS.flush();
    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());
        OS.flush();

        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,
                           SectionKind::getReadOnly());
    StaticDtorSection =
        Ctx.getCOFFSection(".CRT$XTX", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                                           COFF::IMAGE_SCN_MEM_READ,
                           SectionKind::getReadOnly());
  } else {
    StaticCtorSection = Ctx.getCOFFSection(
        ".ctors", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                      COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE,
        SectionKind::getData());
    StaticDtorSection = Ctx.getCOFFSection(
        ".dtors", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                      COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE,
        SectionKind::getData());
  }
}

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.
    SmallString<24> Name;
    raw_svector_ostream OS(Name);
    OS << ".CRT$X" << (IsCtor ? "C" : "T") <<
        (Priority < 200 ? 'A' : 'T') << format("%05u", Priority);
    MCSectionCOFF *Sec = Ctx.getCOFFSection(
        Name, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ,
        SectionKind::getReadOnly());
    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,
                         SectionKind::getData()),
      KeySym, 0);
}

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

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

const MCExpr *TargetLoweringObjectFileCOFF::lowerRelativeReference(
    const GlobalValue *LHS, const GlobalValue *RHS,
    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;

  return MCSymbolRefExpr::create(TM.getSymbol(LHS),
                                 MCSymbolRefExpr::VK_COFF_IMGREL32,
                                 getContext());
}

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)) {
    return APIntToHexString(CFP->getValueAPF().bitcastToAPInt());
  } else if (const auto *CI = dyn_cast<ConstantInt>(C)) {
    return APIntToHexString(CI->getValue());
  } 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 {
  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, Kind,
                                         COMDATSymName,
                                         COFF::IMAGE_COMDAT_SELECT_ANY);
  }

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

//===----------------------------------------------------------------------===//
//                                  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) {
  unsigned Flags = 0;

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

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

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

  return Flags;
}

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 == ".llvmcmd" || Name == ".llvmbc")
    Kind = SectionKind::getMetadata();

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

  unsigned Flags = getWasmSectionFlags(Kind);
  MCSectionWasm *Section = getContext().getWasmSection(
      Name, Kind, Flags, Group, MCContext::GenericSectionID);

  return Section;
}

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

  bool UniqueSectionNames = TM.getUniqueSectionNames();
  SmallString<128> Name = getSectionPrefixForGlobal(Kind);

  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 = MCContext::GenericSectionID;
  if (EmitUniqueSection && !UniqueSectionNames) {
    UniqueID = *NextUniqueID;
    (*NextUniqueID)++;
  }

  unsigned Flags = getWasmSectionFlags(Kind);
  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();

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

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

const MCExpr *TargetLoweringObjectFileWasm::lowerRelativeReference(
    const GlobalValue *LHS, const GlobalValue *RHS,
    const TargetMachine &TM) const {
  // We may only use a PLT-relative relocation to refer to unnamed_addr
  // functions.
  if (!LHS->hasGlobalUnnamedAddr() || !LHS->getValueType()->isFunctionTy())
    return nullptr;

  // Basic correctness checks.
  if (LHS->getType()->getPointerAddressSpace() != 0 ||
      RHS->getType()->getPointerAddressSpace() != 0 || LHS->isThreadLocal() ||
      RHS->isThreadLocal())
    return nullptr;

  return MCBinaryExpr::createSub(
      MCSymbolRefExpr::create(TM.getSymbol(LHS), MCSymbolRefExpr::VK_None,
                              getContext()),
      MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext());
}

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) {
  return MF->getMMI().getContext().getOrCreateSymbol(
      "__ehinfo." + Twine(MF->getFunctionNumber()));
}

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.
  // 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 (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
      if (GVar->hasAttribute("toc-data"))
        return cast<MCSectionXCOFF>(
                   SectionForGlobal(GVar, SectionKind::getData(), TM))
            ->getQualNameSymbol();

    if (GO->isDeclarationForLinker())
      return cast<MCSectionXCOFF>(getSectionForExternalReference(GO, TM))
          ->getQualNameSymbol();

    SectionKind GOKind = getKindForGlobal(GO, TM);
    if (GOKind.isText())
      return cast<MCSectionXCOFF>(
                 getSectionForFunctionDescriptor(cast<Function>(GO), TM))
          ->getQualNameSymbol();
    if ((TM.getDataSections() && !GO->hasSection()) || GO->hasCommonLinkage() ||
        GOKind.isBSSLocal() || GOKind.isThreadBSSLocal())
      return cast<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.isReadOnlyWithRel() || Kind.isBSS())
    MappingClass = 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);

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

  // 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);
      return getContext().getXCOFFSection(
          Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_TD, XCOFF::XTY_SD),
          /* 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.isMergeableCString()) {
    Align Alignment = GO->getParent()->getDataLayout().getPreferredAlign(
        cast<GlobalVariable>(GO));

    unsigned EntrySize = getEntrySizeForKind(Kind);
    std::string SizeSpec = ".rodata.str" + utostr(EntrySize) + ".";
    SmallString<128> Name;
    Name = SizeSpec + utostr(Alignment.value());

    if (TM.getDataSections())
      getNameWithPrefix(Name, GO, TM);

    return getContext().getXCOFFSection(
        Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD),
        /* MultiSymbolsAllowed*/ !TM.getDataSections());
  }

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

  // TODO: We may put Kind.isReadOnlyWithRel() under option control, because
  // user may want to have read-only data with relocations placed into a
  // read-only section by the compiler.
  // 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 defintions, 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 {
  // 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;
}

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

const MCExpr *TargetLoweringObjectFileXCOFF::lowerRelativeReference(
    const GlobalValue *LHS, const GlobalValue *RHS,
    const TargetMachine &TM) const {
  /* Not implemented yet, but don't crash, return nullptr. */
  return nullptr;
}

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<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->isDeclaration()) &&
      isa<Function>(Func)) {
    return getContext()
        .getXCOFFSection(
            NameStr, SectionKind::getText(),
            XCOFF::CsectProperties(XCOFF::XMC_PR, Func->isDeclaration()
                                                      ? XCOFF::XTY_ER
                                                      : XCOFF::XTY_SD))
        ->getQualNameSymbol();
  }

  return getContext().getOrCreateSymbol(NameStr);
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForFunctionDescriptor(
    const Function *F, const TargetMachine &TM) const {
  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 {
  // Use TE storage-mapping class when large code model is enabled so that
  // the chance of needing -bbigtoc is decreased.
  return getContext().getXCOFFSection(
      cast<MCSymbolXCOFF>(Sym)->getSymbolTableName(), SectionKind::getData(),
      XCOFF::CsectProperties(
          TM.getCodeModel() == CodeModel::Large ? XCOFF::XMC_TE : XCOFF::XMC_TC,
          XCOFF::XTY_SD));
}

MCSection *TargetLoweringObjectFileXCOFF::getSectionForLSDA(
    const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
  auto *LSDA = 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;

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

MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
    const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
  auto *Symbol = TM.getSymbol(GO);
  if (Kind.isBSS())
    return getContext().getGOFFSection(Symbol->getName(), SectionKind::getBSS(),
                                       nullptr, nullptr);

  return getContext().getObjectFileInfo()->getTextSection();
}
