//===- AsmPrinter.cpp - Common AsmPrinter code ----------------------------===//
//
// 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 the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "CodeViewDebug.h"
#include "DwarfDebug.h"
#include "DwarfException.h"
#include "PseudoProbePrinter.h"
#include "WasmException.h"
#include "WinCFGuard.h"
#include "WinException.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/AsmPrinterAnalysis.h"
#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/InsertCodePrefetch.h"
#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBlockHashInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/config.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GCStrategy.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalIFunc.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMRemarkStreamer.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PseudoProbe.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSectionXCOFF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/Pass.h"
#include "llvm/Remarks/RemarkStreamer.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VCSRevision.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
#include <cassert>
#include <cinttypes>
#include <cstdint>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "asm-printer"

// This is a replication of fields of object::PGOAnalysisMap::Features. It
// should match the order of the fields so that
// `object::PGOAnalysisMap::Features::decode(PgoAnalysisMapFeatures.getBits())`
// succeeds.
enum class PGOMapFeaturesEnum {
  None,
  FuncEntryCount,
  BBFreq,
  BrProb,
  PropellerCFG,
  All,
};
static cl::bits<PGOMapFeaturesEnum> PgoAnalysisMapFeatures(
    "pgo-analysis-map", cl::Hidden, cl::CommaSeparated,
    cl::values(
        clEnumValN(PGOMapFeaturesEnum::None, "none", "Disable all options"),
        clEnumValN(PGOMapFeaturesEnum::FuncEntryCount, "func-entry-count",
                   "Function Entry Count"),
        clEnumValN(PGOMapFeaturesEnum::BBFreq, "bb-freq",
                   "Basic Block Frequency"),
        clEnumValN(PGOMapFeaturesEnum::BrProb, "br-prob", "Branch Probability"),
        clEnumValN(PGOMapFeaturesEnum::All, "all", "Enable all options")),
    cl::desc(
        "Enable extended information within the SHT_LLVM_BB_ADDR_MAP that is "
        "extracted from PGO related analysis."));

static cl::opt<bool> PgoAnalysisMapEmitBBSectionsCfg(
    "pgo-analysis-map-emit-bb-sections-cfg",
    cl::desc("Enable the post-link cfg information from the basic block "
             "sections profile in the PGO analysis map"),
    cl::Hidden, cl::init(false));

static cl::opt<bool> BBAddrMapSkipEmitBBEntries(
    "basic-block-address-map-skip-bb-entries",
    cl::desc("Skip emitting basic block entries in the SHT_LLVM_BB_ADDR_MAP "
             "section. It's used to save binary size when BB entries are "
             "unnecessary for some PGOAnalysisMap features."),
    cl::Hidden, cl::init(false));

static cl::opt<bool> EmitJumpTableSizesSection(
    "emit-jump-table-sizes-section",
    cl::desc("Emit a section containing jump table addresses and sizes"),
    cl::Hidden, cl::init(false));

// This isn't turned on by default, since several of the scheduling models are
// not completely accurate, and we don't want to be misleading.
static cl::opt<bool> PrintLatency(
    "asm-print-latency",
    cl::desc("Print instruction latencies as verbose asm comments"), cl::Hidden,
    cl::init(false));

static cl::opt<std::string>
    StackUsageFile("stack-usage-file",
                   cl::desc("Output filename for stack usage information"),
                   cl::value_desc("filename"), cl::Hidden);

extern cl::opt<bool> EmitBBHash;

STATISTIC(EmittedInsts, "Number of machine instrs printed");

char AsmPrinter::ID = 0;

namespace {
class AddrLabelMapCallbackPtr final : CallbackVH {
  AddrLabelMap *Map = nullptr;

public:
  AddrLabelMapCallbackPtr() = default;
  AddrLabelMapCallbackPtr(Value *V) : CallbackVH(V) {}

  void setPtr(BasicBlock *BB) {
    ValueHandleBase::operator=(BB);
  }

  void setMap(AddrLabelMap *map) { Map = map; }

  void deleted() override;
  void allUsesReplacedWith(Value *V2) override;
};
} // namespace

class llvm::AddrLabelMap {
  MCContext &Context;
  struct AddrLabelSymEntry {
    /// The symbols for the label.
    TinyPtrVector<MCSymbol *> Symbols;

    Function *Fn;   // The containing function of the BasicBlock.
    unsigned Index; // The index in BBCallbacks for the BasicBlock.
  };

  DenseMap<AssertingVH<BasicBlock>, AddrLabelSymEntry> AddrLabelSymbols;

  /// Callbacks for the BasicBlock's that we have entries for.  We use this so
  /// we get notified if a block is deleted or RAUWd.
  std::vector<AddrLabelMapCallbackPtr> BBCallbacks;

  /// This is a per-function list of symbols whose corresponding BasicBlock got
  /// deleted.  These symbols need to be emitted at some point in the file, so
  /// AsmPrinter emits them after the function body.
  DenseMap<AssertingVH<Function>, std::vector<MCSymbol *>>
      DeletedAddrLabelsNeedingEmission;

public:
  AddrLabelMap(MCContext &context) : Context(context) {}

  ~AddrLabelMap() {
    assert(DeletedAddrLabelsNeedingEmission.empty() &&
           "Some labels for deleted blocks never got emitted");
  }

  ArrayRef<MCSymbol *> getAddrLabelSymbolToEmit(BasicBlock *BB);

  void takeDeletedSymbolsForFunction(Function *F,
                                     std::vector<MCSymbol *> &Result);

  void UpdateForDeletedBlock(BasicBlock *BB);
  void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New);
};

ArrayRef<MCSymbol *> AddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) {
  assert(BB->hasAddressTaken() &&
         "Shouldn't get label for block without address taken");
  AddrLabelSymEntry &Entry = AddrLabelSymbols[BB];

  // If we already had an entry for this block, just return it.
  if (!Entry.Symbols.empty()) {
    assert(BB->getParent() == Entry.Fn && "Parent changed");
    return Entry.Symbols;
  }

  // Otherwise, this is a new entry, create a new symbol for it and add an
  // entry to BBCallbacks so we can be notified if the BB is deleted or RAUWd.
  BBCallbacks.emplace_back(BB);
  BBCallbacks.back().setMap(this);
  Entry.Index = BBCallbacks.size() - 1;
  Entry.Fn = BB->getParent();
  MCSymbol *Sym = BB->hasAddressTaken() ? Context.createNamedTempSymbol()
                                        : Context.createTempSymbol();
  Entry.Symbols.push_back(Sym);
  return Entry.Symbols;
}

/// If we have any deleted symbols for F, return them.
void AddrLabelMap::takeDeletedSymbolsForFunction(
    Function *F, std::vector<MCSymbol *> &Result) {
  DenseMap<AssertingVH<Function>, std::vector<MCSymbol *>>::iterator I =
      DeletedAddrLabelsNeedingEmission.find(F);

  // If there are no entries for the function, just return.
  if (I == DeletedAddrLabelsNeedingEmission.end())
    return;

  // Otherwise, take the list.
  std::swap(Result, I->second);
  DeletedAddrLabelsNeedingEmission.erase(I);
}

//===- Address of Block Management ----------------------------------------===//

ArrayRef<MCSymbol *>
AsmPrinter::getAddrLabelSymbolToEmit(const BasicBlock *BB) {
  // Lazily create AddrLabelSymbols.
  if (!AddrLabelSymbols)
    AddrLabelSymbols = std::make_unique<AddrLabelMap>(OutContext);
  return AddrLabelSymbols->getAddrLabelSymbolToEmit(
      const_cast<BasicBlock *>(BB));
}

void AsmPrinter::takeDeletedSymbolsForFunction(
    const Function *F, std::vector<MCSymbol *> &Result) {
  // If no blocks have had their addresses taken, we're done.
  if (!AddrLabelSymbols)
    return;
  return AddrLabelSymbols->takeDeletedSymbolsForFunction(
      const_cast<Function *>(F), Result);
}

void AddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) {
  // If the block got deleted, there is no need for the symbol.  If the symbol
  // was already emitted, we can just forget about it, otherwise we need to
  // queue it up for later emission when the function is output.
  AddrLabelSymEntry Entry = std::move(AddrLabelSymbols[BB]);
  AddrLabelSymbols.erase(BB);
  assert(!Entry.Symbols.empty() && "Didn't have a symbol, why a callback?");
  BBCallbacks[Entry.Index] = nullptr; // Clear the callback.

#if !LLVM_MEMORY_SANITIZER_BUILD
  // BasicBlock is destroyed already, so this access is UB detectable by msan.
  assert((BB->getParent() == nullptr || BB->getParent() == Entry.Fn) &&
         "Block/parent mismatch");
#endif

  for (MCSymbol *Sym : Entry.Symbols) {
    if (Sym->isDefined())
      return;

    // If the block is not yet defined, we need to emit it at the end of the
    // function.  Add the symbol to the DeletedAddrLabelsNeedingEmission list
    // for the containing Function.  Since the block is being deleted, its
    // parent may already be removed, we have to get the function from 'Entry'.
    DeletedAddrLabelsNeedingEmission[Entry.Fn].push_back(Sym);
  }
}

void AddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) {
  // Get the entry for the RAUW'd block and remove it from our map.
  AddrLabelSymEntry OldEntry = std::move(AddrLabelSymbols[Old]);
  AddrLabelSymbols.erase(Old);
  assert(!OldEntry.Symbols.empty() && "Didn't have a symbol, why a callback?");

  AddrLabelSymEntry &NewEntry = AddrLabelSymbols[New];

  // If New is not address taken, just move our symbol over to it.
  if (NewEntry.Symbols.empty()) {
    BBCallbacks[OldEntry.Index].setPtr(New); // Update the callback.
    NewEntry = std::move(OldEntry);          // Set New's entry.
    return;
  }

  BBCallbacks[OldEntry.Index] = nullptr; // Update the callback.

  // Otherwise, we need to add the old symbols to the new block's set.
  llvm::append_range(NewEntry.Symbols, OldEntry.Symbols);
}

void AddrLabelMapCallbackPtr::deleted() {
  Map->UpdateForDeletedBlock(cast<BasicBlock>(getValPtr()));
}

void AddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) {
  Map->UpdateForRAUWBlock(cast<BasicBlock>(getValPtr()), cast<BasicBlock>(V2));
}

/// getGVAlignment - Return the alignment to use for the specified global
/// value.  This rounds up to the preferred alignment if possible and legal.
Align AsmPrinter::getGVAlignment(const GlobalObject *GV, const DataLayout &DL,
                                 Align InAlign) {
  Align Alignment;
  if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
    Alignment = DL.getPreferredAlign(GVar);

  // If InAlign is specified, round it to it.
  if (InAlign > Alignment)
    Alignment = InAlign;

  // If the GV has a specified alignment, take it into account.
  MaybeAlign GVAlign;
  if (auto *GVar = dyn_cast<GlobalVariable>(GV))
    GVAlign = GVar->getAlign();
  else if (auto *F = dyn_cast<Function>(GV))
    GVAlign = F->getAlign();
  if (!GVAlign)
    return Alignment;

  assert(GVAlign && "GVAlign must be set");

  // If the GVAlign is larger than NumBits, or if we are required to obey
  // NumBits because the GV has an assigned section, obey it.
  if (*GVAlign > Alignment || GV->hasSection())
    Alignment = *GVAlign;
  return Alignment;
}

AsmPrinter::AsmPrinter(TargetMachine &tm, std::unique_ptr<MCStreamer> Streamer,
                       char &ID)
    : MachineFunctionPass(ID), TM(tm), MAI(tm.getMCAsmInfo()),
      OutContext(Streamer->getContext()), OutStreamer(std::move(Streamer)),
      SM(*this) {
  VerboseAsm = OutStreamer->isVerboseAsm();
  DwarfUsesRelocationsAcrossSections =
      MAI.doesDwarfUseRelocationsAcrossSections();
  GetMMI = [this]() {
    auto *MMIWP = getAnalysisIfAvailable<MachineModuleInfoWrapperPass>();
    return MMIWP ? &MMIWP->getMMI() : nullptr;
  };
  GetORE = [this](MachineFunction &MF) {
    return &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
  };
  GetMDT = [this](MachineFunction &MF) {
    auto *MDTWrapper =
        getAnalysisIfAvailable<MachineDominatorTreeWrapperPass>();
    return MDTWrapper ? &MDTWrapper->getDomTree() : nullptr;
  };
  GetMLI = [this](MachineFunction &MF) {
    auto *MLIWrapper = getAnalysisIfAvailable<MachineLoopInfoWrapperPass>();
    return MLIWrapper ? &MLIWrapper->getLI() : nullptr;
  };
  BeginGCAssembly = [this](Module &M) {
    GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
    assert(MI && "AsmPrinter didn't require GCModuleInfo?");
    for (const auto &I : *MI)
      if (GCMetadataPrinter *MP = getOrCreateGCPrinter(*I))
        MP->beginAssembly(M, *MI, *this);
  };
  FinishGCAssembly = [this](Module &M) {
    GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
    assert(MI && "AsmPrinter didn't require GCModuleInfo?");
    for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E;)
      if (GCMetadataPrinter *MP = getOrCreateGCPrinter(**--I))
        MP->finishAssembly(M, *MI, *this);
  };
  EmitStackMaps = [this](Module &M) {
    GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
    assert(MI && "AsmPrinter didn't require GCModuleInfo?");
    bool NeedsDefault = false;
    if (MI->begin() == MI->end())
      // No GC strategy, use the default format.
      NeedsDefault = true;
    else
      for (const auto &I : *MI) {
        if (GCMetadataPrinter *MP = getOrCreateGCPrinter(*I))
          if (MP->emitStackMaps(SM, *this))
            continue;
        // The strategy doesn't have printer or doesn't emit custom stack maps.
        // Use the default format.
        NeedsDefault = true;
      }

    if (NeedsDefault)
      SM.serializeToStackMapSection();
  };
  AssertDebugEHFinalized = [&]() {
    assert(!DD && Handlers.size() == NumUserHandlers &&
           "Debug/EH info didn't get finalized");
  };
}

AsmPrinter::~AsmPrinter() { AssertDebugEHFinalized(); }

bool AsmPrinter::isPositionIndependent() const {
  return TM.isPositionIndependent();
}

/// getFunctionNumber - Return a unique ID for the current function.
unsigned AsmPrinter::getFunctionNumber() const {
  return MF->getFunctionNumber();
}

const TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const {
  return *TM.getObjFileLowering();
}

const DataLayout &AsmPrinter::getDataLayout() const {
  assert(MMI && "MMI could not be nullptr!");
  return MMI->getModule()->getDataLayout();
}

// Do not use the cached DataLayout because some client use it without a Module
// (dsymutil, llvm-dwarfdump).
unsigned AsmPrinter::getPointerSize() const {
  return TM.getPointerSize(0); // FIXME: Default address space
}

const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const {
  assert(MF && "getSubtargetInfo requires a valid MachineFunction!");
  return MF->getSubtarget<MCSubtargetInfo>();
}

void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
  S.emitInstruction(Inst, getSubtargetInfo());
}

/// getCurrentSection() - Return the current section we are emitting to.
const MCSection *AsmPrinter::getCurrentSection() const {
  return OutStreamer->getCurrentSectionOnly();
}

/// createDwarfDebug() - Create the DwarfDebug handler.
DwarfDebug *AsmPrinter::createDwarfDebug() { return new DwarfDebug(this); }

void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  MachineFunctionPass::getAnalysisUsage(AU);
  AU.addRequired<MachineOptimizationRemarkEmitterPass>();
  AU.addRequired<GCModuleInfo>();
  AU.addRequired<LazyMachineBlockFrequencyInfoPass>();
  AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
  if (EmitBBHash)
    AU.addRequired<MachineBlockHashInfo>();
  AU.addUsedIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>();
}

bool AsmPrinter::doInitialization(Module &M) {
  MMI = GetMMI();
  HasSplitStack = false;
  HasNoSplitStack = false;
  DbgInfoAvailable = !M.debug_compile_units().empty();
  const Triple &Target = TM.getTargetTriple();

  AddrLabelSymbols = nullptr;

  // Initialize TargetLoweringObjectFile.
  TM.getObjFileLowering()->Initialize(OutContext, TM);

  TM.getObjFileLowering()->getModuleMetadata(M);

  // On AIX, we delay emitting any section information until
  // after emitting the .file pseudo-op. This allows additional
  // information (such as the embedded command line) to be associated
  // with all sections in the object file rather than a single section.
  if (!Target.isOSBinFormatXCOFF())
    OutStreamer->initSections(TM.getMCSubtargetInfo());

  // Emit the version-min deployment target directive if needed.
  //
  // FIXME: If we end up with a collection of these sorts of Darwin-specific
  // or ELF-specific things, it may make sense to have a platform helper class
  // that will work with the target helper class. For now keep it here, as the
  // alternative is duplicated code in each of the target asm printers that
  // use the directive, where it would need the same conditionalization
  // anyway.
  if (Target.isOSBinFormatMachO() && Target.isOSDarwin()) {
    Triple TVT(M.getDarwinTargetVariantTriple());
    OutStreamer->emitVersionForTarget(
        Target, M.getSDKVersion(),
        M.getDarwinTargetVariantTriple().empty() ? nullptr : &TVT,
        M.getDarwinTargetVariantSDKVersion());
  }

  // Allow the target to emit any magic that it wants at the start of the file.
  emitStartOfAsmFile(M);

  // Very minimal debug info. It is ignored if we emit actual debug info. If we
  // don't, this at least helps the user find where a global came from.
  if (MAI.hasSingleParameterDotFile()) {
    // .file "foo.c"
    if (MAI.isAIX()) {
      const char VerStr[] =
#ifdef PACKAGE_VENDOR
          PACKAGE_VENDOR " "
#endif
          PACKAGE_NAME " version " PACKAGE_VERSION
#ifdef LLVM_REVISION
                         " (" LLVM_REVISION ")"
#endif
          ;
      // TODO: Add timestamp and description.
      OutStreamer->emitFileDirective(M.getSourceFileName(), VerStr, "", "");
    } else {
      OutStreamer->emitFileDirective(
          llvm::sys::path::filename(M.getSourceFileName()));
    }
  }

  // On AIX, emit bytes for llvm.commandline metadata after .file so that the
  // C_INFO symbol is preserved if any csect is kept by the linker.
  if (Target.isOSBinFormatXCOFF()) {
    emitModuleCommandLines(M);
    // Now we can generate section information.
    OutStreamer->switchSection(
        OutContext.getObjectFileInfo()->getTextSection());

    // To work around an AIX assembler and/or linker bug, generate
    // a rename for the default text-section symbol name.  This call has
    // no effect when generating object code directly.
    MCSection *TextSection =
        OutStreamer->getContext().getObjectFileInfo()->getTextSection();
    MCSymbolXCOFF *XSym =
        static_cast<MCSectionXCOFF *>(TextSection)->getQualNameSymbol();
    if (XSym->hasRename())
      OutStreamer->emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
  }

  BeginGCAssembly(M);

  // Emit module-level inline asm if it exists.
  if (M.hasModuleInlineAsm()) {
    OutStreamer->AddComment("Start of file scope inline assembly");
    OutStreamer->addBlankLine();
    for (const Module::GlobalAsmFragment &Frag : M.getModuleInlineAsm()) {
      const MCSubtargetInfo &AsmSTI = TM.getMCSubtargetInfo(
          Frag.Props.TargetCPU, Frag.Props.TargetFeatures);
      bool DidPush = emitTargetFeaturePush(AsmSTI);
      emitInlineAsm(
          Frag.Asm, AsmSTI, TM.Options.MCOptions, nullptr,
          InlineAsm::AsmDialect(TM.getMCAsmInfo().getAssemblerDialect()));
      emitTargetFeaturePop(AsmSTI, DidPush);
    }
    OutStreamer->AddComment("End of file scope inline assembly");
    OutStreamer->addBlankLine();
  }

  if (MAI.doesSupportDebugInformation()) {
    bool EmitCodeView = M.getCodeViewFlag();
    // On Windows targets, emit minimal CodeView compiler info even when debug
    // info is disabled.
    if ((Target.isOSWindows() || (Target.isUEFI() && EmitCodeView)) &&
        M.getNamedMetadata("llvm.dbg.cu"))
      Handlers.push_back(std::make_unique<CodeViewDebug>(this));
    if (!EmitCodeView || M.getDwarfVersion()) {
      if (hasDebugInfo()) {
        DD = createDwarfDebug();
        Handlers.push_back(std::unique_ptr<DwarfDebug>(DD));
      }
    }
  }

  if (M.getNamedMetadata(PseudoProbeDescMetadataName))
    PP = std::make_unique<PseudoProbeHandler>(this);

  switch (MAI.getExceptionHandlingType()) {
  case ExceptionHandling::None:
    // We may want to emit CFI for debug.
    [[fallthrough]];
  case ExceptionHandling::SjLj:
  case ExceptionHandling::DwarfCFI:
  case ExceptionHandling::ARM:
    for (auto &F : M.getFunctionList()) {
      if (getFunctionCFISectionType(F) != CFISection::None)
        ModuleCFISection = getFunctionCFISectionType(F);
      // If any function needsUnwindTableEntry(), it needs .eh_frame and hence
      // the module needs .eh_frame. If we have found that case, we are done.
      if (ModuleCFISection == CFISection::EH)
        break;
    }
    assert(MAI.getExceptionHandlingType() == ExceptionHandling::DwarfCFI ||
           usesCFIWithoutEH() || ModuleCFISection != CFISection::EH);
    break;
  default:
    break;
  }

  EHStreamer *ES = nullptr;
  switch (MAI.getExceptionHandlingType()) {
  case ExceptionHandling::None:
    if (!usesCFIWithoutEH())
      break;
    [[fallthrough]];
  case ExceptionHandling::SjLj:
  case ExceptionHandling::DwarfCFI:
  case ExceptionHandling::ZOS:
    ES = new DwarfCFIException(this);
    break;
  case ExceptionHandling::ARM:
    ES = new ARMException(this);
    break;
  case ExceptionHandling::WinEH:
    switch (MAI.getWinEHEncodingType()) {
    default: llvm_unreachable("unsupported unwinding information encoding");
    case WinEH::EncodingType::Invalid:
      break;
    case WinEH::EncodingType::X86:
    case WinEH::EncodingType::Itanium:
      ES = new WinException(this);
      break;
    }
    break;
  case ExceptionHandling::Wasm:
    ES = new WasmException(this);
    break;
  case ExceptionHandling::AIX:
    ES = new AIXException(this);
    break;
  }
  if (ES)
    EHHandlers.push_back(std::unique_ptr<EHStreamer>(ES));

  // All CFG modes required the tables emitted.
  if (M.getControlFlowGuardMode() != ControlFlowGuardMode::Disabled)
    Handlers.push_back(std::make_unique<WinCFGuard>(this));

  for (auto &Handler : Handlers)
    Handler->beginModule(&M);
  for (auto &Handler : EHHandlers)
    Handler->beginModule(&M);

  return false;
}

static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) {
  if (!MAI.hasWeakDefCanBeHiddenDirective())
    return false;

  return GV->canBeOmittedFromSymbolTable();
}

void AsmPrinter::emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
  GlobalValue::LinkageTypes Linkage = GV->getLinkage();
  switch (Linkage) {
  case GlobalValue::CommonLinkage:
  case GlobalValue::LinkOnceAnyLinkage:
  case GlobalValue::LinkOnceODRLinkage:
  case GlobalValue::WeakAnyLinkage:
  case GlobalValue::WeakODRLinkage:
    if (MAI.isMachO()) {
      // .globl _foo
      OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);

      if (!canBeHidden(GV, MAI))
        // .weak_definition _foo
        OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefinition);
      else
        OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate);
    } else if (MAI.avoidWeakIfComdat() && GV->hasComdat()) {
      // .globl _foo
      OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);
      //NOTE: linkonce is handled by the section the symbol was assigned to.
    } else {
      // .weak _foo
      OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak);
    }
    return;
  case GlobalValue::ExternalLinkage:
    OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);
    return;
  case GlobalValue::PrivateLinkage:
  case GlobalValue::InternalLinkage:
    return;
  case GlobalValue::ExternalWeakLinkage:
  case GlobalValue::AvailableExternallyLinkage:
  case GlobalValue::AppendingLinkage:
    llvm_unreachable("Should never emit this");
  }
  llvm_unreachable("Unknown linkage type!");
}

void AsmPrinter::getNameWithPrefix(SmallVectorImpl<char> &Name,
                                   const GlobalValue *GV) const {
  TM.getNameWithPrefix(Name, GV, getObjFileLowering().getMangler());
}

MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const {
  return TM.getSymbol(GV);
}

MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const {
  // On ELF, use .Lfoo$local if GV is a non-interposable GlobalObject with an
  // exact definion (intersection of GlobalValue::hasExactDefinition() and
  // !isInterposable()). These linkages include: external, appending, internal,
  // private. It may be profitable to use a local alias for external. The
  // assembler would otherwise be conservative and assume a global default
  // visibility symbol can be interposable, even if the code generator already
  // assumed it.
  if (TM.getTargetTriple().isOSBinFormatELF() && GV.canBenefitFromLocalAlias()) {
    const Module &M = *GV.getParent();
    if (TM.getRelocationModel() != Reloc::Static &&
        M.getPIELevel() == PIELevel::Default && GV.isDSOLocal())
      return getSymbolWithGlobalValueBase(&GV, "$local");
  }
  return TM.getSymbol(&GV);
}

/// EmitGlobalVariable - Emit the specified global variable to the .s file.
void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
  MaybeAlign AlignmentGranule = getRequiredGlobalAlignmentGranule(*GV);
  emitGlobalVariable(GV, AlignmentGranule);
  if (AlignmentGranule)
    OutStreamer->emitValueToAlignment(*AlignmentGranule);
}

void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV,
                                    MaybeAlign AlignmentGranule) {
  bool IsEmuTLSVar = TM.useEmulatedTLS() && GV->isThreadLocal();
  assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) &&
         "No emulated TLS variables in the common section");

  // Never emit TLS variable xyz in emulated TLS model.
  // The initialization value is in __emutls_t.xyz instead of xyz.
  if (IsEmuTLSVar)
    return;

  if (GV->hasInitializer()) {
    // Check to see if this is a special global used by LLVM, if so, emit it.
    if (emitSpecialLLVMGlobal(GV))
      return;

    // Skip the emission of global equivalents. The symbol can be emitted later
    // on by emitGlobalGOTEquivs in case it turns out to be needed.
    if (GlobalGOTEquivs.count(getSymbol(GV)))
      return;

    if (isVerbose()) {
      // When printing the control variable __emutls_v.*,
      // we don't need to print the original TLS variable name.
      GV->printAsOperand(OutStreamer->getCommentOS(),
                         /*PrintType=*/false, GV->getParent());
      OutStreamer->getCommentOS() << '\n';
    }
  }

  MCSymbol *GVSym = getSymbol(GV);
  MCSymbol *EmittedSym = GVSym;

  // getOrCreateEmuTLSControlSym only creates the symbol with name and default
  // attributes.
  // GV's or GVSym's attributes will be used for the EmittedSym.
  emitVisibility(EmittedSym, GV->getVisibility(), !GV->isDeclaration());

  if (GV->isTagged()) {
    Triple T = TM.getTargetTriple();

    if (T.getArch() != Triple::aarch64)
      OutContext.reportError(SMLoc(),
                             "tagged symbols (-fsanitize=memtag-globals) are "
                             "only supported on AArch64");
    OutStreamer->emitSymbolAttribute(EmittedSym, MCSA_Memtag);
  }

  if (!GV->hasInitializer())   // External globals require no extra code.
    return;

  GVSym->redefineIfPossible();
  if (GVSym->isDefined() || GVSym->isVariable())
    OutContext.reportError(SMLoc(), "symbol '" + Twine(GVSym->getName()) +
                                        "' is already defined");

  if (MAI.hasDotTypeDotSizeDirective())
    OutStreamer->emitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject);

  SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);

  const DataLayout &DL = GV->getDataLayout();
  uint64_t Size = GV->getGlobalSize(DL);

  // If the alignment is specified, we *must* obey it.  Overaligning a global
  // with a specified alignment is a prompt way to break globals emitted to
  // sections and expected to be contiguous (e.g. ObjC metadata).
  //
  // If we get passed in an explicit alignment granule, it is up to the caller
  // to ensure that is not the case (i.e. that the GV is not in a section).
  Align Alignment = getGVAlignment(GV, DL);

  if (AlignmentGranule) {
    assert(!GV->hasSection());
    Size = alignTo(Size, *AlignmentGranule);
    if (Alignment < *AlignmentGranule)
      Alignment = *AlignmentGranule;
  }

  for (auto &Handler : Handlers)
    Handler->setSymbolSize(GVSym, Size);

  // Handle common symbols
  if (GVKind.isCommon()) {
    if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
    // .comm _foo, 42, 4
    OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
    return;
  }

  // Determine to which section this global should be emitted.
  MCSection *TheSection = getObjFileLowering().SectionForGlobal(GV, GVKind, TM);

  // If we have a bss global going to a section that supports the
  // zerofill directive, do so here.
  if (GVKind.isBSS() && MAI.isMachO() && TheSection->isBssSection()) {
    if (Size == 0)
      Size = 1; // zerofill of 0 bytes is undefined.
    emitLinkage(GV, GVSym);
    // .zerofill __DATA, __bss, _foo, 400, 5
    OutStreamer->emitZerofill(TheSection, GVSym, Size, Alignment);
    return;
  }

  // If this is a BSS local symbol and we are emitting in the BSS
  // section use .lcomm/.comm directive.
  if (GVKind.isBSSLocal() &&
      getObjFileLowering().getBSSSection() == TheSection) {
    if (Size == 0)
      Size = 1; // .comm Foo, 0 is undefined, avoid it.

    // Use .lcomm only if it supports user-specified alignment.
    // Otherwise, while it would still be correct to use .lcomm in some
    // cases (e.g. when Align == 1), the external assembler might enfore
    // some -unknown- default alignment behavior, which could cause
    // spurious differences between external and integrated assembler.
    // Prefer to simply fall back to .local / .comm in this case.
    if (MAI.getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) {
      // .lcomm _foo, 42
      OutStreamer->emitLocalCommonSymbol(GVSym, Size, Alignment);
      return;
    }

    // .local _foo
    OutStreamer->emitSymbolAttribute(GVSym, MCSA_Local);
    // .comm _foo, 42, 4
    OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
    return;
  }

  // Handle thread local data for mach-o which requires us to output an
  // additional structure of data and mangle the original symbol so that we
  // can reference it later.
  //
  // TODO: This should become an "emit thread local global" method on TLOF.
  // All of this macho specific stuff should be sunk down into TLOFMachO and
  // stuff like "TLSExtraDataSection" should no longer be part of the parent
  // TLOF class.  This will also make it more obvious that stuff like
  // MCStreamer::EmitTBSSSymbol is macho specific and only called from macho
  // specific code.
  if (GVKind.isThreadLocal() && MAI.isMachO()) {
    // Emit the .tbss symbol
    MCSymbol *MangSym =
        OutContext.getOrCreateSymbol(GVSym->getName() + Twine("$tlv$init"));

    if (GVKind.isThreadBSS()) {
      TheSection = getObjFileLowering().getTLSBSSSection();
      OutStreamer->emitTBSSSymbol(TheSection, MangSym, Size, Alignment);
    } else if (GVKind.isThreadData()) {
      OutStreamer->switchSection(TheSection);

      emitAlignment(Alignment, GV);
      OutStreamer->emitLabel(MangSym);

      emitGlobalConstant(GV->getDataLayout(),
                         GV->getInitializer());
    }

    OutStreamer->addBlankLine();

    // Emit the variable struct for the runtime.
    MCSection *TLVSect = getObjFileLowering().getTLSExtraDataSection();

    OutStreamer->switchSection(TLVSect);
    // Emit the linkage here.
    emitLinkage(GV, GVSym);
    OutStreamer->emitLabel(GVSym);

    // Three pointers in size:
    //   - __tlv_bootstrap - used to make sure support exists
    //   - spare pointer, used when mapped by the runtime
    //   - pointer to mangled symbol above with initializer
    unsigned PtrSize = DL.getPointerTypeSize(GV->getType());
    OutStreamer->emitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"),
                                PtrSize);
    OutStreamer->emitIntValue(0, PtrSize);
    OutStreamer->emitSymbolValue(MangSym, PtrSize);

    OutStreamer->addBlankLine();
    return;
  }

  MCSymbol *EmittedInitSym = GVSym;

  OutStreamer->switchSection(TheSection);

  emitLinkage(GV, EmittedInitSym);
  emitAlignment(Alignment, GV);

  OutStreamer->emitLabel(EmittedInitSym);
  MCSymbol *LocalAlias = getSymbolPreferLocal(*GV);
  if (LocalAlias != EmittedInitSym)
    OutStreamer->emitLabel(LocalAlias);

  emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());

  if (MAI.hasDotTypeDotSizeDirective())
    // .size foo, 42
    OutStreamer->emitELFSize(EmittedInitSym,
                             MCConstantExpr::create(Size, OutContext));

  OutStreamer->addBlankLine();
}

/// Emit the directive and value for debug thread local expression
///
/// \p Value - The value to emit.
/// \p Size - The size of the integer (in bytes) to emit.
void AsmPrinter::emitDebugValue(const MCExpr *Value, unsigned Size) const {
  OutStreamer->emitValue(Value, Size);
}

void AsmPrinter::emitFunctionHeaderComment() {}

void AsmPrinter::emitFunctionPrefix(ArrayRef<const Constant *> Prefix) {
  const Function &F = MF->getFunction();
  if (!MAI.hasSubsectionsViaSymbols()) {
    for (auto &C : Prefix)
      emitGlobalConstant(F.getDataLayout(), C);
    return;
  }
  // Preserving prefix-like data on platforms which use subsections-via-symbols
  // is a bit tricky. Here we introduce a symbol for the prefix-like data
  // and use the .alt_entry attribute to mark the function's real entry point
  // as an alternative entry point to the symbol that precedes the function..
  OutStreamer->emitLabel(OutContext.createLinkerPrivateTempSymbol());

  for (auto &C : Prefix) {
    emitGlobalConstant(F.getDataLayout(), C);
  }

  // Emit an .alt_entry directive for the actual function symbol.
  OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_AltEntry);
}

/// EmitFunctionHeader - This method emits the header for the current
/// function.
void AsmPrinter::emitFunctionHeader() {
  const Function &F = MF->getFunction();

  if (isVerbose())
    OutStreamer->getCommentOS()
        << "-- Begin function "
        << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';

  // Print out constants referenced by the function
  emitConstantPool();

  // Print the 'header' of function.
  // If basic block sections are desired, explicitly request a unique section
  // for this function's entry block.
  if (MF->front().isBeginSection())
    MF->setSection(getObjFileLowering().getUniqueSectionForFunction(F, TM));
  else
    MF->setSection(getObjFileLowering().SectionForGlobal(&F, TM));
  OutStreamer->switchSection(MF->getSection());

  if (MAI.isAIX())
    emitLinkage(&F, CurrentFnDescSym);
  else
    emitVisibility(CurrentFnSym, F.getVisibility());

  emitLinkage(&F, CurrentFnSym);
  if (MAI.hasFunctionAlignment()) {
    Align PrefAlign = MF->getPreferredAlignment();
    if (MAI.useIntegratedAssembler() && MAI.hasPreferredAlignment()) {
      // Emit .p2align for the effective minimum alignment (which accounts for
      // F's own align attribute via getGVAlignment), then emit .prefalign only
      // when the preferred alignment is greater. The end symbol must be
      // created here, before the function body, so that .prefalign can
      // reference it; emitFunctionBody will emit the label at the function
      // end.
      Align MinAlign = emitAlignment(MF->getAlignment(), &F);
      if (MinAlign < PrefAlign) {
        CurrentFnEnd = createTempSymbol("func_end");
        OutStreamer->emitPrefAlign(PrefAlign, *CurrentFnEnd,
                                   /*EmitNops=*/true, /*Fill=*/0,
                                   getSubtargetInfo());
      }
    } else {
      emitAlignment(PrefAlign, &F);
    }
  }

  if (MAI.hasDotTypeDotSizeDirective())
    OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);

  if (F.hasFnAttribute(Attribute::Cold))
    OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_Cold);

  // Emit the prefix data.
  if (F.hasPrefixData())
    emitFunctionPrefix({F.getPrefixData()});

  // Emit KCFI type information before patchable-function-prefix nops.
  emitKCFITypeId(*MF);

  // Emit M NOPs for -fpatchable-function-entry=N,M where M>0. We arbitrarily
  // place prefix data before NOPs.
  unsigned PatchableFunctionPrefix =
      F.getFnAttributeAsParsedInteger("patchable-function-prefix");
  unsigned PatchableFunctionEntry =
      F.getFnAttributeAsParsedInteger("patchable-function-entry");
  if (PatchableFunctionPrefix) {
    CurrentPatchableFunctionEntrySym =
        OutContext.createLinkerPrivateTempSymbol();
    OutStreamer->emitLabel(CurrentPatchableFunctionEntrySym);
    emitNops(PatchableFunctionPrefix);
  } else if (PatchableFunctionEntry) {
    // May be reassigned when emitting the body, to reference the label after
    // the initial BTI (AArch64) or endbr32/endbr64 (x86).
    CurrentPatchableFunctionEntrySym = CurrentFnBegin;
  }

  // Emit the function prologue data for the indirect call sanitizer.
  if (const MDNode *MD = F.getMetadata(LLVMContext::MD_func_sanitize)) {
    assert(MD->getNumOperands() == 2);

    auto *PrologueSig = mdconst::extract<Constant>(MD->getOperand(0));
    auto *TypeHash = mdconst::extract<Constant>(MD->getOperand(1));
    emitFunctionPrefix({PrologueSig, TypeHash});
  }

  if (isVerbose()) {
    F.printAsOperand(OutStreamer->getCommentOS(),
                     /*PrintType=*/false, F.getParent());
    emitFunctionHeaderComment();
    OutStreamer->getCommentOS() << '\n';
  }

  // Emit the function descriptor. This is a virtual function to allow targets
  // to emit their specific function descriptor. Right now it is only used by
  // the AIX target. The PowerPC 64-bit V1 ELF target also uses function
  // descriptors and should be converted to use this hook as well.
  if (MAI.isAIX())
    emitFunctionDescriptor();

  // Emit the CurrentFnSym. This is a virtual function to allow targets to do
  // their wild and crazy things as required.
  emitFunctionEntryLabel();

  // If the function had address-taken blocks that got deleted, then we have
  // references to the dangling symbols.  Emit them at the start of the function
  // so that we don't get references to undefined symbols.
  std::vector<MCSymbol*> DeadBlockSyms;
  takeDeletedSymbolsForFunction(&F, DeadBlockSyms);
  for (MCSymbol *DeadBlockSym : DeadBlockSyms) {
    OutStreamer->AddComment("Address taken block that was later removed");
    OutStreamer->emitLabel(DeadBlockSym);
  }

  if (CurrentFnBegin) {
    if (MAI.useAssignmentForEHBegin()) {
      MCSymbol *CurPos = OutContext.createTempSymbol();
      OutStreamer->emitLabel(CurPos);
      OutStreamer->emitAssignment(CurrentFnBegin,
                                 MCSymbolRefExpr::create(CurPos, OutContext));
    } else {
      OutStreamer->emitLabel(CurrentFnBegin);
    }
  }

  // Emit pre-function debug and/or EH information.
  for (auto &Handler : Handlers) {
    Handler->beginFunction(MF);
    Handler->beginBasicBlockSection(MF->front());
  }
  for (auto &Handler : EHHandlers) {
    Handler->beginFunction(MF);
    Handler->beginBasicBlockSection(MF->front());
  }

  // Emit the prologue data.
  if (F.hasPrologueData())
    emitGlobalConstant(F.getDataLayout(), F.getPrologueData());
}

/// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the
/// function.  This can be overridden by targets as required to do custom stuff.
void AsmPrinter::emitFunctionEntryLabel() {
  CurrentFnSym->redefineIfPossible();
  OutStreamer->emitLabel(CurrentFnSym);

  if (TM.getTargetTriple().isOSBinFormatELF()) {
    MCSymbol *Sym = getSymbolPreferLocal(MF->getFunction());
    if (Sym != CurrentFnSym) {
      CurrentFnBeginLocal = Sym;
      OutStreamer->emitLabel(Sym);
      OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
    }
  }
}

/// emitComments - Pretty-print comments for instructions.
static void emitComments(const MachineInstr &MI, const MCSubtargetInfo *STI,
                         raw_ostream &CommentOS) {
  const MachineFunction *MF = MI.getMF();
  const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();

  // Check for spills and reloads

  // We assume a single instruction only has a spill or reload, not
  // both.
  std::optional<LocationSize> Size;
  if ((Size = MI.getRestoreSize(TII))) {
    CommentOS << Size->getValue() << "-byte Reload\n";
  } else if ((Size = MI.getFoldedRestoreSize(TII))) {
    if (!Size->hasValue())
      CommentOS << "Unknown-size Folded Reload\n";
    else if (Size->getValue())
      CommentOS << Size->getValue() << "-byte Folded Reload\n";
  } else if ((Size = MI.getSpillSize(TII))) {
    CommentOS << Size->getValue() << "-byte Spill\n";
  } else if ((Size = MI.getFoldedSpillSize(TII))) {
    if (!Size->hasValue())
      CommentOS << "Unknown-size Folded Spill\n";
    else if (Size->getValue())
      CommentOS << Size->getValue() << "-byte Folded Spill\n";
  }

  // Check for spill-induced copies
  if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse))
    CommentOS << " Reload Reuse\n";

  if (PrintLatency) {
    const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
    const MCSchedModel &SCModel = STI->getSchedModel();
    int Latency = SCModel.computeInstrLatency<MCSubtargetInfo, MCInstrInfo,
                                              InstrItineraryData, MachineInstr>(
        *STI, *TII, MI);
    // Report only interesting latencies.
    if (1 < Latency)
      CommentOS << " Latency: " << Latency << "\n";
  }
}

/// emitImplicitDef - This method emits the specified machine instruction
/// that is an implicit def.
void AsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
  Register RegNo = MI->getOperand(0).getReg();

  SmallString<128> Str;
  raw_svector_ostream OS(Str);
  OS << "implicit-def: "
     << printReg(RegNo, MF->getSubtarget().getRegisterInfo());

  OutStreamer->AddComment(OS.str());
  OutStreamer->addBlankLine();
}

static void emitKill(const MachineInstr *MI, AsmPrinter &AP) {
  std::string Str;
  raw_string_ostream OS(Str);
  OS << "kill:";
  for (const MachineOperand &Op : MI->operands()) {
    assert(Op.isReg() && "KILL instruction must have only register operands");
    OS << ' ' << (Op.isDef() ? "def " : "killed ")
       << printReg(Op.getReg(), AP.MF->getSubtarget().getRegisterInfo());
  }
  AP.OutStreamer->AddComment(Str);
  AP.OutStreamer->addBlankLine();
}

static void emitFakeUse(const MachineInstr *MI, AsmPrinter &AP) {
  std::string Str;
  raw_string_ostream OS(Str);
  OS << "fake_use:";
  for (const MachineOperand &Op : MI->operands()) {
    // In some circumstances we can end up with fake uses of constants; skip
    // these.
    if (!Op.isReg())
      continue;
    OS << ' ' << printReg(Op.getReg(), AP.MF->getSubtarget().getRegisterInfo());
  }
  AP.OutStreamer->AddComment(OS.str());
  AP.OutStreamer->addBlankLine();
}

/// emitDebugValueComment - This method handles the target-independent form
/// of DBG_VALUE, returning true if it was able to do so.  A false return
/// means the target will need to handle MI in EmitInstruction.
static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
  // This code handles only the 4-operand target-independent form.
  if (MI->isNonListDebugValue() && MI->getNumOperands() != 4)
    return false;

  SmallString<128> Str;
  raw_svector_ostream OS(Str);
  OS << "DEBUG_VALUE: ";

  const DILocalVariable *V = MI->getDebugVariable();
  if (auto *SP = dyn_cast<DISubprogram>(V->getScope())) {
    StringRef Name = SP->getName();
    if (!Name.empty())
      OS << Name << ":";
  }
  OS << V->getName();
  OS << " <- ";

  const DIExpression *Expr = MI->getDebugExpression();
  // First convert this to a non-variadic expression if possible, to simplify
  // the output.
  if (auto NonVariadicExpr = DIExpression::convertToNonVariadicExpression(Expr))
    Expr = *NonVariadicExpr;
  // Then, output the possibly-simplified expression.
  if (Expr->getNumElements()) {
    OS << '[';
    ListSeparator LS;
    for (auto &Op : Expr->expr_ops()) {
      OS << LS << dwarf::OperationEncodingString(Op.getOp());
      for (unsigned I = 0; I < Op.getNumArgs(); ++I)
        OS << ' ' << Op.getArg(I);
    }
    OS << "] ";
  }

  // Register or immediate value. Register 0 means undef.
  for (const MachineOperand &Op : MI->debug_operands()) {
    if (&Op != MI->debug_operands().begin())
      OS << ", ";
    switch (Op.getType()) {
    case MachineOperand::MO_FPImmediate: {
      APFloat APF = APFloat(Op.getFPImm()->getValueAPF());
      Type *ImmTy = Op.getFPImm()->getType();
      if (ImmTy->isBFloatTy() || ImmTy->isHalfTy() || ImmTy->isFloatTy() ||
          ImmTy->isDoubleTy()) {
        OS << APF.convertToDouble();
      } else {
        // There is no good way to print long double.  Convert a copy to
        // double.  Ah well, it's only a comment.
        bool ignored;
        APF.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
                    &ignored);
        OS << "(long double) " << APF.convertToDouble();
      }
      break;
    }
    case MachineOperand::MO_Immediate: {
      OS << Op.getImm();
      break;
    }
    case MachineOperand::MO_CImmediate: {
      Op.getCImm()->getValue().print(OS, false /*isSigned*/);
      break;
    }
    case MachineOperand::MO_TargetIndex: {
      OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")";
      break;
    }
    case MachineOperand::MO_Register:
    case MachineOperand::MO_FrameIndex: {
      Register Reg;
      std::optional<StackOffset> Offset;
      if (Op.isReg()) {
        Reg = Op.getReg();
      } else {
        const TargetFrameLowering *TFI =
            AP.MF->getSubtarget().getFrameLowering();
        Offset = TFI->getFrameIndexReference(*AP.MF, Op.getIndex(), Reg);
      }
      if (!Reg) {
        // Suppress offset, it is not meaningful here.
        OS << "undef";
        break;
      }
      // The second operand is only an offset if it's an immediate.
      if (MI->isIndirectDebugValue())
        Offset = StackOffset::getFixed(MI->getDebugOffset().getImm());
      if (Offset)
        OS << '[';
      OS << printReg(Reg, AP.MF->getSubtarget().getRegisterInfo());
      if (Offset)
        OS << '+' << Offset->getFixed() << ']';
      break;
    }
    default:
      llvm_unreachable("Unknown operand type");
    }
  }

  // NOTE: Want this comment at start of line, don't emit with AddComment.
  AP.OutStreamer->emitRawComment(Str);
  return true;
}

/// This method handles the target-independent form of DBG_LABEL, returning
/// true if it was able to do so.  A false return means the target will need
/// to handle MI in EmitInstruction.
static bool emitDebugLabelComment(const MachineInstr *MI, AsmPrinter &AP) {
  if (MI->getNumOperands() != 1)
    return false;

  SmallString<128> Str;
  raw_svector_ostream OS(Str);
  OS << "DEBUG_LABEL: ";

  const DILabel *V = MI->getDebugLabel();
  if (auto *SP = dyn_cast<DISubprogram>(
          V->getScope()->getNonLexicalBlockFileScope())) {
    StringRef Name = SP->getName();
    if (!Name.empty())
      OS << Name << ":";
  }
  OS << V->getName();

  // NOTE: Want this comment at start of line, don't emit with AddComment.
  AP.OutStreamer->emitRawComment(OS.str());
  return true;
}

AsmPrinter::CFISection
AsmPrinter::getFunctionCFISectionType(const Function &F) const {
  // Ignore functions that won't get emitted.
  if (F.isDeclarationForLinker())
    return CFISection::None;

  if (MAI.getExceptionHandlingType() == ExceptionHandling::DwarfCFI &&
      F.needsUnwindTableEntry())
    return CFISection::EH;

  if (MAI.usesCFIWithoutEH() && F.hasUWTable())
    return CFISection::EH;

  if (hasDebugInfo() || TM.Options.ForceDwarfFrameSection)
    return CFISection::Debug;

  return CFISection::None;
}

AsmPrinter::CFISection
AsmPrinter::getFunctionCFISectionType(const MachineFunction &MF) const {
  return getFunctionCFISectionType(MF.getFunction());
}

bool AsmPrinter::needsSEHMoves() {
  return MAI.usesWindowsCFI() && MF->getFunction().needsUnwindTableEntry();
}

bool AsmPrinter::usesCFIWithoutEH() const {
  return MAI.usesCFIWithoutEH() && ModuleCFISection != CFISection::None;
}

void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) {
  ExceptionHandling ExceptionHandlingType = MAI.getExceptionHandlingType();
  if (!usesCFIWithoutEH() &&
      ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
      ExceptionHandlingType != ExceptionHandling::ARM)
    return;

  if (getFunctionCFISectionType(*MF) == CFISection::None)
    return;

  // If there is no "real" instruction following this CFI instruction, skip
  // emitting it; it would be beyond the end of the function's FDE range.
  auto *MBB = MI.getParent();
  auto I = std::next(MI.getIterator());
  while (I != MBB->end() && I->isTransient())
    ++I;
  if (I == MBB->instr_end() &&
      MBB->getReverseIterator() == MBB->getParent()->rbegin())
    return;

  const std::vector<MCCFIInstruction> &Instrs = MF->getFrameInstructions();
  unsigned CFIIndex = MI.getOperand(0).getCFIIndex();
  const MCCFIInstruction &CFI = Instrs[CFIIndex];
  emitCFIInstruction(CFI);
}

void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) {
  // The operands are the MCSymbol and the frame offset of the allocation.
  MCSymbol *FrameAllocSym = MI.getOperand(0).getMCSymbol();
  int FrameOffset = MI.getOperand(1).getImm();

  // Emit a symbol assignment.
  OutStreamer->emitAssignment(FrameAllocSym,
                             MCConstantExpr::create(FrameOffset, OutContext));
}

/// Returns the BB metadata to be emitted in the SHT_LLVM_BB_ADDR_MAP section
/// for a given basic block. This can be used to capture more precise profile
/// information.
static uint32_t getBBAddrMapMetadata(const MachineBasicBlock &MBB) {
  const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
  return object::BBAddrMap::BBEntry::Metadata{
      MBB.isReturnBlock(), !MBB.empty() && TII->isTailCall(MBB.back()),
      MBB.isEHPad(), const_cast<MachineBasicBlock &>(MBB).canFallThrough(),
      !MBB.empty() && MBB.rbegin()->isIndirectBranch()}
      .encode();
}

static llvm::object::BBAddrMap::Features
getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges,
                    bool HasCalls, const CFGProfile *FuncCFGProfile) {
  // Ensure that the user has not passed in additional options while also
  // specifying all or none.
  if ((PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::None) ||
       PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::All)) &&
      popcount(PgoAnalysisMapFeatures.getBits()) != 1) {
    MF.getFunction().getContext().emitError(
        "-pgo-analysis-map can accept only all or none with no additional "
        "values.");
  }

  bool NoFeatures = PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::None);
  bool AllFeatures = PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::All);
  bool FuncEntryCountEnabled =
      AllFeatures || (!NoFeatures && PgoAnalysisMapFeatures.isSet(
                                         PGOMapFeaturesEnum::FuncEntryCount));
  bool BBFreqEnabled =
      AllFeatures ||
      (!NoFeatures && PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::BBFreq));
  bool BrProbEnabled =
      AllFeatures ||
      (!NoFeatures && PgoAnalysisMapFeatures.isSet(PGOMapFeaturesEnum::BrProb));
  bool PostLinkCfgEnabled = FuncCFGProfile && PgoAnalysisMapEmitBBSectionsCfg;

  if ((BBFreqEnabled || BrProbEnabled) && BBAddrMapSkipEmitBBEntries) {
    MF.getFunction().getContext().emitError(
        "BB entries info is required for BBFreq and BrProb features");
  }
  return {FuncEntryCountEnabled, BBFreqEnabled, BrProbEnabled,
          MF.hasBBSections() && NumMBBSectionRanges > 1,
          // Use static_cast to avoid breakage of tests on windows.
          static_cast<bool>(BBAddrMapSkipEmitBBEntries), HasCalls,
          static_cast<bool>(EmitBBHash), PostLinkCfgEnabled};
}

void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
  MCSection *BBAddrMapSection =
      getObjFileLowering().getBBAddrMapSection(*MF.getSection());
  assert(BBAddrMapSection && ".llvm_bb_addr_map section is not initialized.");
  bool HasCalls = !CurrentFnCallsiteEndSymbols.empty();

  const BasicBlockSectionsProfileReader *BBSPR = nullptr;
  if (auto *BBSPRPass =
          getAnalysisIfAvailable<BasicBlockSectionsProfileReaderWrapperPass>())
    BBSPR = &BBSPRPass->getBBSPR();
  const CFGProfile *FuncCFGProfile = nullptr;
  if (BBSPR)
    FuncCFGProfile = BBSPR->getFunctionCFGProfile(MF.getFunction().getName());

  const MCSymbol *FunctionSymbol = getFunctionBegin();

  OutStreamer->pushSection();
  OutStreamer->switchSection(BBAddrMapSection);
  OutStreamer->AddComment("version");
  uint8_t BBAddrMapVersion = OutStreamer->getContext().getBBAddrMapVersion();
  OutStreamer->emitInt8(BBAddrMapVersion);
  OutStreamer->AddComment("feature");
  auto Features = getBBAddrMapFeature(MF, MBBSectionRanges.size(), HasCalls,
                                      FuncCFGProfile);
  OutStreamer->emitInt16(Features.encode());
  // Emit BB Information for each basic block in the function.
  if (Features.MultiBBRange) {
    OutStreamer->AddComment("number of basic block ranges");
    OutStreamer->emitULEB128IntValue(MBBSectionRanges.size());
  }
  // Number of blocks in each MBB section.
  DenseMap<MBBSectionID, unsigned> MBBSectionNumBlocks;
  const MCSymbol *PrevMBBEndSymbol = nullptr;
  if (!Features.MultiBBRange) {
    OutStreamer->AddComment("function address");
    OutStreamer->emitSymbolValue(FunctionSymbol, getPointerSize());
    OutStreamer->AddComment("number of basic blocks");
    OutStreamer->emitULEB128IntValue(MF.size());
    PrevMBBEndSymbol = FunctionSymbol;
  } else {
    unsigned BBCount = 0;
    for (const MachineBasicBlock &MBB : MF) {
      BBCount++;
      if (MBB.isEndSection()) {
        // Store each section's basic block count when it ends.
        MBBSectionNumBlocks[MBB.getSectionID()] = BBCount;
        // Reset the count for the next section.
        BBCount = 0;
      }
    }
  }
  // Emit the BB entry for each basic block in the function.
  for (const MachineBasicBlock &MBB : MF) {
    const MCSymbol *MBBSymbol =
        MBB.isEntryBlock() ? FunctionSymbol : MBB.getSymbol();
    bool IsBeginSection =
        Features.MultiBBRange && (MBB.isBeginSection() || MBB.isEntryBlock());
    if (IsBeginSection) {
      OutStreamer->AddComment("base address");
      OutStreamer->emitSymbolValue(MBBSymbol, getPointerSize());
      OutStreamer->AddComment("number of basic blocks");
      OutStreamer->emitULEB128IntValue(MBBSectionNumBlocks[MBB.getSectionID()]);
      PrevMBBEndSymbol = MBBSymbol;
    }

    auto MBHI =
        Features.BBHash ? &getAnalysis<MachineBlockHashInfo>() : nullptr;

    if (!Features.OmitBBEntries) {
      OutStreamer->AddComment("BB id");
      // Emit the BB ID for this basic block.
      // We only emit BaseID since CloneID is unset for
      // -basic-block-adress-map.
      // TODO: Emit the full BBID when labels and sections can be mixed
      // together.
      OutStreamer->emitULEB128IntValue(MBB.getBBID()->BaseID);
      // Emit the basic block offset relative to the end of the previous block.
      // This is zero unless the block is padded due to alignment.
      emitLabelDifferenceAsULEB128(MBBSymbol, PrevMBBEndSymbol);
      const MCSymbol *CurrentLabel = MBBSymbol;
      if (HasCalls) {
        auto CallsiteEndSymbols = CurrentFnCallsiteEndSymbols.lookup(&MBB);
        OutStreamer->AddComment("number of callsites");
        OutStreamer->emitULEB128IntValue(CallsiteEndSymbols.size());
        for (const MCSymbol *CallsiteEndSymbol : CallsiteEndSymbols) {
          // Emit the callsite offset.
          emitLabelDifferenceAsULEB128(CallsiteEndSymbol, CurrentLabel);
          CurrentLabel = CallsiteEndSymbol;
        }
      }
      // Emit the offset to the end of the block, which can be used to compute
      // the total block size.
      emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), CurrentLabel);
      // Emit the Metadata.
      OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB));
      // Emit the Hash.
      if (MBHI) {
        OutStreamer->emitInt64(MBHI->getMBBHash(MBB));
      }
    }
    PrevMBBEndSymbol = MBB.getEndSymbol();
  }

  if (Features.hasPGOAnalysis()) {
    assert(BBAddrMapVersion >= 2 &&
           "PGOAnalysisMap only supports version 2 or later");

    if (Features.FuncEntryCount) {
      OutStreamer->AddComment("function entry count");
      auto MaybeEntryCount = MF.getFunction().getEntryCount();
      OutStreamer->emitULEB128IntValue(MaybeEntryCount ? *MaybeEntryCount : 0);
    }
    const MachineBlockFrequencyInfo *MBFI =
        Features.BBFreq
            ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
            : nullptr;
    const MachineBranchProbabilityInfo *MBPI =
        Features.BrProb
            ? &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI()
            : nullptr;

    if (Features.BBFreq || Features.BrProb) {
      for (const MachineBasicBlock &MBB : MF) {
        if (Features.BBFreq) {
          OutStreamer->AddComment("basic block frequency");
          OutStreamer->emitULEB128IntValue(
              MBFI->getBlockFreq(&MBB).getFrequency());
          if (Features.PostLinkCfg) {
            OutStreamer->AddComment("basic block frequency (propeller)");
            OutStreamer->emitULEB128IntValue(
                FuncCFGProfile->getBlockCount(*MBB.getBBID()));
          }
        }
        if (Features.BrProb) {
          unsigned SuccCount = MBB.succ_size();
          OutStreamer->AddComment("basic block successor count");
          OutStreamer->emitULEB128IntValue(SuccCount);
          for (const MachineBasicBlock *SuccMBB : MBB.successors()) {
            OutStreamer->AddComment("successor BB ID");
            OutStreamer->emitULEB128IntValue(SuccMBB->getBBID()->BaseID);
            OutStreamer->AddComment("successor branch probability");
            OutStreamer->emitULEB128IntValue(
                MBPI->getEdgeProbability(&MBB, SuccMBB).getNumerator());
            if (Features.PostLinkCfg) {
              OutStreamer->AddComment("successor branch frequency (propeller)");
              OutStreamer->emitULEB128IntValue(FuncCFGProfile->getEdgeCount(
                  *MBB.getBBID(), *SuccMBB->getBBID()));
            }
          }
        }
      }
    }
  }

  OutStreamer->popSection();
}

void AsmPrinter::emitKCFITrapEntry(const MachineFunction &MF,
                                   const MCSymbol *Symbol) {
  MCSection *Section =
      getObjFileLowering().getKCFITrapSection(*MF.getSection());
  if (!Section)
    return;

  OutStreamer->pushSection();
  OutStreamer->switchSection(Section);

  MCSymbol *Loc = OutContext.createLinkerPrivateTempSymbol();
  OutStreamer->emitLabel(Loc);
  OutStreamer->emitAbsoluteSymbolDiff(Symbol, Loc, 4);

  OutStreamer->popSection();
}

void AsmPrinter::emitKCFITypeId(const MachineFunction &MF) {
  const Function &F = MF.getFunction();
  if (const MDNode *MD = F.getMetadata(LLVMContext::MD_kcfi_type))
    emitGlobalConstant(F.getDataLayout(),
                       mdconst::extract<ConstantInt>(MD->getOperand(0)));
}

void AsmPrinter::emitPseudoProbe(const MachineInstr &MI) {
  if (PP) {
    auto GUID = MI.getOperand(0).getImm();
    auto Index = MI.getOperand(1).getImm();
    auto Type = MI.getOperand(2).getImm();
    auto Attr = MI.getOperand(3).getImm();
    DILocation *DebugLoc = MI.getDebugLoc();
    PP->emitPseudoProbe(GUID, Index, Type, Attr, DebugLoc);
  }
}

void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) {
  if (!MF.getTarget().Options.EmitStackSizeSection)
    return;

  MCSection *StackSizeSection =
      getObjFileLowering().getStackSizesSection(*MF.getSection());
  if (!StackSizeSection)
    return;

  const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
  // Don't emit functions with dynamic stack allocations.
  if (FrameInfo.hasVarSizedObjects())
    return;

  OutStreamer->pushSection();
  OutStreamer->switchSection(StackSizeSection);

  const MCSymbol *FunctionSymbol = getFunctionBegin();
  uint64_t StackSize =
      FrameInfo.getStackSize() + FrameInfo.getUnsafeStackSize();
  OutStreamer->emitSymbolValue(FunctionSymbol, TM.getProgramPointerSize());
  OutStreamer->emitULEB128IntValue(StackSize);

  OutStreamer->popSection();
}

void AsmPrinter::emitStackUsage(const MachineFunction &MF) {
  const std::string OutputFilename =
      !StackUsageFile.empty() ? StackUsageFile
                              : MF.getTarget().Options.StackUsageFile;

  // OutputFilename empty implies -fstack-usage is not passed.
  if (OutputFilename.empty())
    return;

  const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
  uint64_t StackSize =
      FrameInfo.getStackSize() + FrameInfo.getUnsafeStackSize();

  if (StackUsageStream == nullptr) {
    std::error_code EC;
    StackUsageStream =
        std::make_unique<raw_fd_ostream>(OutputFilename, EC, sys::fs::OF_Text);
    if (EC) {
      errs() << "Could not open file: " << EC.message();
      return;
    }
  }

  if (const DISubprogram *DSP = MF.getFunction().getSubprogram())
    *StackUsageStream << DSP->getFilename() << ':' << DSP->getLine();
  else
    *StackUsageStream << MF.getFunction().getParent()->getName();

  *StackUsageStream << ':' << MF.getName() << '\t' << StackSize << '\t';
  if (FrameInfo.hasVarSizedObjects())
    *StackUsageStream << "dynamic\n";
  else
    *StackUsageStream << "static\n";
}

/// Extracts a numeric type identifier of a Function's type from
/// callgraph metadata. Returns null if metadata cannot be found.
static ConstantInt *extractNumericCGTypeId(const Function &F) {
  SmallVector<MDNode *, 2> Types;
  F.getMetadata(LLVMContext::MD_callgraph, Types);
  for (const auto &Type : Types) {
    if (Type->getNumOperands() == 1 && isa<MDString>(Type->getOperand(0))) {
      MDString *MDTypeId = cast<MDString>(Type->getOperand(0));
      uint64_t TypeIdVal = llvm::MD5Hash(MDTypeId->getString());
      IntegerType *Int64Ty = Type::getInt64Ty(F.getContext());
      return ConstantInt::get(Int64Ty, TypeIdVal);
    }
  }
  return nullptr;
}

/// Emits .llvm.callgraph section.
void AsmPrinter::emitCallGraphSection(const MachineFunction &MF,
                                      FunctionCallGraphInfo &FuncCGInfo) {
  if (!MF.getTarget().Options.EmitCallGraphSection)
    return;

  // Switch to the call graph section for the function
  MCSection *FuncCGSection =
      getObjFileLowering().getCallGraphSection(*getCurrentSection());
  assert(FuncCGSection && "null callgraph section");
  OutStreamer->pushSection();
  OutStreamer->switchSection(FuncCGSection);

  const Function &F = MF.getFunction();
  // If this function has external linkage or has its address taken and
  // it is not a callback, then anything could call it.
  bool IsIndirectTarget =
      !F.hasLocalLinkage() || F.hasAddressTaken(nullptr,
                                                /*IgnoreCallbackUses=*/true,
                                                /*IgnoreAssumeLikeCalls=*/true,
                                                /*IgnoreLLVMUsed=*/false);

  const auto &DirectCallees = FuncCGInfo.DirectCallees;
  const auto &IndirectCalleeTypeIDs = FuncCGInfo.IndirectCalleeTypeIDs;

  using namespace callgraph;
  Flags CGFlags = Flags::None;
  if (IsIndirectTarget)
    CGFlags |= Flags::IsIndirectTarget;
  if (DirectCallees.size() > 0)
    CGFlags |= Flags::HasDirectCallees;
  if (IndirectCalleeTypeIDs.size() > 0)
    CGFlags |= Flags::HasIndirectCallees;

  // Emit function's call graph information.
  // 1) CallGraphSectionFormatVersion
  // 2) Flags
  //    a. LSB bit 0 is set to 1 if the function is a potential indirect
  //       target.
  //    b. LSB bit 1 is set to 1 if there are direct callees.
  //    c. LSB bit 2 is set to 1 if there are indirect callees.
  //    d. Rest of the 5 bits in Flags are reserved for any future use.
  // 3) Function entry PC.
  // 4) FunctionTypeID if the function is indirect target and its type id
  //    is known, otherwise it is set to 0.
  // 5) Number of unique direct callees, if at least one exists.
  // 6) For each unique direct callee, the callee's PC.
  // 7) Number of unique indirect target type IDs, if at least one exists.
  // 8) Each unique indirect target type id.
  OutStreamer->emitInt8(CallGraphSectionFormatVersion::V_0);
  OutStreamer->emitInt8(static_cast<uint8_t>(CGFlags));
  OutStreamer->emitSymbolValue(getSymbol(&F), TM.getProgramPointerSize());
  const auto *TypeId = extractNumericCGTypeId(F);
  if (IsIndirectTarget && TypeId)
    OutStreamer->emitInt64(TypeId->getZExtValue());
  else
    OutStreamer->emitInt64(0);

  if (DirectCallees.size() > 0) {
    OutStreamer->emitULEB128IntValue(DirectCallees.size());
    for (const auto &CalleeSymbol : DirectCallees)
      OutStreamer->emitSymbolValue(CalleeSymbol, TM.getProgramPointerSize());
    FuncCGInfo.DirectCallees.clear();
  }
  if (IndirectCalleeTypeIDs.size() > 0) {
    OutStreamer->emitULEB128IntValue(IndirectCalleeTypeIDs.size());
    for (const auto &CalleeTypeId : IndirectCalleeTypeIDs)
      OutStreamer->emitInt64(CalleeTypeId);
    FuncCGInfo.IndirectCalleeTypeIDs.clear();
  }
  // End of emitting call graph section contents.
  OutStreamer->popSection();
}

void AsmPrinter::emitPCSectionsLabel(const MachineFunction &MF,
                                     const MDNode &MD) {
  MCSymbol *S = MF.getContext().createTempSymbol("pcsection");
  OutStreamer->emitLabel(S);
  PCSectionsSymbols[&MD].emplace_back(S);
}

void AsmPrinter::emitPCSections(const MachineFunction &MF) {
  const Function &F = MF.getFunction();
  if (PCSectionsSymbols.empty() && !F.hasMetadata(LLVMContext::MD_pcsections))
    return;

  const CodeModel::Model CM = MF.getTarget().getCodeModel();
  const unsigned RelativeRelocSize =
      (CM == CodeModel::Medium || CM == CodeModel::Large) ? getPointerSize()
                                                          : 4;

  // Switch to PCSection, short-circuiting the common case where the current
  // section is still valid (assume most MD_pcsections contain just 1 section).
  auto SwitchSection = [&, Prev = StringRef()](const StringRef &Sec) mutable {
    if (Sec == Prev)
      return;
    MCSection *S = getObjFileLowering().getPCSection(Sec, MF.getSection());
    assert(S && "PC section is not initialized");
    OutStreamer->switchSection(S);
    Prev = Sec;
  };
  // Emit symbols into sections and data as specified in the pcsections MDNode.
  auto EmitForMD = [&](const MDNode &MD, ArrayRef<const MCSymbol *> Syms,
                       bool Deltas) {
    // Expect the first operand to be a section name. After that, a tuple of
    // constants may appear, which will simply be emitted into the current
    // section (the user of MD_pcsections decides the format of encoded data).
    assert(isa<MDString>(MD.getOperand(0)) && "first operand not a string");
    bool ConstULEB128 = false;
    for (const MDOperand &MDO : MD.operands()) {
      if (auto *S = dyn_cast<MDString>(MDO)) {
        // Found string, start of new section!
        // Find options for this section "<section>!<opts>" - supported options:
        //   C = Compress constant integers of size 2-8 bytes as ULEB128.
        const StringRef SecWithOpt = S->getString();
        const size_t OptStart = SecWithOpt.find('!'); // likely npos
        const StringRef Sec = SecWithOpt.substr(0, OptStart);
        const StringRef Opts = SecWithOpt.substr(OptStart); // likely empty
        ConstULEB128 = Opts.contains('C');
#ifndef NDEBUG
        for (char O : Opts)
          assert((O == '!' || O == 'C') && "Invalid !pcsections options");
#endif
        SwitchSection(Sec);
        const MCSymbol *Prev = Syms.front();
        for (const MCSymbol *Sym : Syms) {
          if (Sym == Prev || !Deltas) {
            // Use the entry itself as the base of the relative offset.
            MCSymbol *Base = MF.getContext().createTempSymbol("pcsection_base");
            OutStreamer->emitLabel(Base);
            // Emit relative relocation `addr - base`, which avoids a dynamic
            // relocation in the final binary. User will get the address with
            // `base + addr`.
            emitLabelDifference(Sym, Base, RelativeRelocSize);
          } else {
            // Emit delta between symbol and previous symbol.
            if (ConstULEB128)
              emitLabelDifferenceAsULEB128(Sym, Prev);
            else
              emitLabelDifference(Sym, Prev, 4);
          }
          Prev = Sym;
        }
      } else {
        // Emit auxiliary data after PC.
        assert(isa<MDNode>(MDO) && "expecting either string or tuple");
        const auto *AuxMDs = cast<MDNode>(MDO);
        for (const MDOperand &AuxMDO : AuxMDs->operands()) {
          assert(isa<ConstantAsMetadata>(AuxMDO) && "expecting a constant");
          const Constant *C = cast<ConstantAsMetadata>(AuxMDO)->getValue();
          const DataLayout &DL = F.getDataLayout();
          const uint64_t Size = DL.getTypeStoreSize(C->getType());

          if (auto *CI = dyn_cast<ConstantInt>(C);
              CI && ConstULEB128 && Size > 1 && Size <= 8) {
            emitULEB128(CI->getZExtValue());
          } else {
            emitGlobalConstant(DL, C);
          }
        }
      }
    }
  };

  OutStreamer->pushSection();
  // Emit PCs for function start and function size.
  if (const MDNode *MD = F.getMetadata(LLVMContext::MD_pcsections))
    EmitForMD(*MD, {getFunctionBegin(), getFunctionEnd()}, true);
  // Emit PCs for instructions collected.
  for (const auto &MS : PCSectionsSymbols)
    EmitForMD(*MS.first, MS.second, false);
  OutStreamer->popSection();
  PCSectionsSymbols.clear();
}

/// Returns true if function begin and end labels should be emitted.
static bool needFuncLabels(const MachineFunction &MF, const AsmPrinter &Asm) {
  if (Asm.hasDebugInfo() || !MF.getLandingPads().empty() ||
      MF.hasEHFunclets() ||
      MF.getFunction().hasMetadata(LLVMContext::MD_pcsections))
    return true;

  // We might emit an EH table that uses function begin and end labels even if
  // we don't have any landingpads.
  if (!MF.getFunction().hasPersonalityFn())
    return false;
  return !isNoOpWithoutInvoke(
      classifyEHPersonality(MF.getFunction().getPersonalityFn()));
}

// Return the mnemonic of a MachineInstr if available, or the MachineInstr
// opcode name otherwise.
static StringRef getMIMnemonic(const MachineInstr &MI, MCStreamer &Streamer) {
  const TargetInstrInfo *TII =
      MI.getParent()->getParent()->getSubtarget().getInstrInfo();
  MCInst MCI;
  MCI.setOpcode(MI.getOpcode());
  if (StringRef Name = Streamer.getMnemonic(MCI); !Name.empty())
    return Name;
  StringRef Name = TII->getName(MI.getOpcode());
  assert(!Name.empty() && "Missing mnemonic and name for opcode");
  return Name;
}

void AsmPrinter::handleCallsiteForCallgraph(
    FunctionCallGraphInfo &FuncCGInfo,
    const MachineFunction::CallSiteInfoMap &CallSitesInfoMap,
    const MachineInstr &MI) {
  assert(MI.isCall() && "This method is meant for call instructions only.");
  const MachineOperand &CalleeOperand = MI.getOperand(0);
  if (CalleeOperand.isGlobal() || CalleeOperand.isSymbol()) {
    // Handle direct calls.
    MCSymbol *CalleeSymbol = nullptr;
    switch (CalleeOperand.getType()) {
    case llvm::MachineOperand::MO_GlobalAddress:
      CalleeSymbol = getSymbol(CalleeOperand.getGlobal());
      break;
    case llvm::MachineOperand::MO_ExternalSymbol:
      CalleeSymbol = GetExternalSymbolSymbol(CalleeOperand.getSymbolName());
      break;
    default:
      llvm_unreachable(
          "Expected to only handle direct call instructions here.");
    }
    FuncCGInfo.DirectCallees.insert(CalleeSymbol);
    return; // Early exit after handling the direct call instruction.
  }
  const auto &CallSiteInfo = CallSitesInfoMap.find(&MI);
  if (CallSiteInfo == CallSitesInfoMap.end())
    return;
  // Handle indirect callsite info.
  // Only indirect calls have type identifiers set.
  for (ConstantInt *CalleeTypeId : CallSiteInfo->second.CalleeTypeIds) {
    uint64_t CalleeTypeIdVal = CalleeTypeId->getZExtValue();
    FuncCGInfo.IndirectCalleeTypeIDs.insert(CalleeTypeIdVal);
  }
}

/// Helper to emit a symbol for the prefetch target associated with the given
/// BBID and callsite index.
void AsmPrinter::emitPrefetchTargetSymbol(const UniqueBBID &BBID,
                                          unsigned CallsiteIndex) {
  SmallString<128> FunctionName;
  getNameWithPrefix(FunctionName, &MF->getFunction());
  MCSymbol *PrefetchTargetSymbol = OutContext.getOrCreateSymbol(
      getPrefetchTargetSymbolName(FunctionName, BBID, CallsiteIndex));
  // If the function is weak-linkage it may be replaced by a strong
  // version, in which case the prefetch targets should also be replaced.
  OutStreamer->emitSymbolAttribute(
      PrefetchTargetSymbol,
      MF->getFunction().isWeakForLinker() ? MCSA_Weak : MCSA_Global);
  OutStreamer->emitLabel(PrefetchTargetSymbol);
}

/// Emit dangling prefetch targets that were not mapped to any basic block.
void AsmPrinter::emitDanglingPrefetchTargets() {
  const DenseMap<UniqueBBID, SmallVector<unsigned>> &MFPrefetchTargets =
      MF->getPrefetchTargets();
  if (MFPrefetchTargets.empty())
    return;
  DenseSet<UniqueBBID> MFBBIDs;
  for (const MachineBasicBlock &MBB : *MF)
    if (std::optional<UniqueBBID> BBID = MBB.getBBID())
      MFBBIDs.insert(*BBID);

  for (const auto &[BBID, CallsiteIndexes] : MFPrefetchTargets) {
    if (MFBBIDs.contains(BBID))
      continue;
    for (unsigned CallsiteIndex : CallsiteIndexes)
      emitPrefetchTargetSymbol(BBID, CallsiteIndex);
  }
}

/// EmitFunctionBody - This method emits the body and trailer for a
/// function.
void AsmPrinter::emitFunctionBody() {
  emitFunctionHeader();

  // Emit target-specific gunk before the function body.
  emitFunctionBodyStart();

  if (isVerbose()) {
    MDT = GetMDT(*MF);
    // Get MachineLoopInfo or compute it on the fly if it's unavailable, which
    // needs a MachineDominatorTree only for an irreducible CFG.
    MLI = GetMLI(*MF);
    if (!MLI) {
      OwnedMLI = std::make_unique<MachineLoopInfo>();
      OwnedMLI->calculate(*MF, [&]() -> const MachineDominatorTree & {
        if (!MDT) {
          OwnedMDT = std::make_unique<MachineDominatorTree>();
          OwnedMDT->recalculate(*MF);
          MDT = OwnedMDT.get();
        }
        return *MDT;
      });
      MLI = OwnedMLI.get();
    }
  }

  // Print out code for the function.
  bool HasAnyRealCode = false;
  int NumInstsInFunction = 0;
  bool IsEHa = MMI->getModule()->getModuleFlag("eh-asynch");

  const MCSubtargetInfo *STI = nullptr;
  if (this->MF)
    STI = &getSubtargetInfo();
  else
    STI = &TM.getMCSubtargetInfo();

  bool CanDoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE);
  // Create a slot for the entry basic block section so that the section
  // order is preserved when iterating over MBBSectionRanges.
  if (!MF->empty())
    MBBSectionRanges[MF->front().getSectionID()] =
        MBBSectionRange{CurrentFnBegin, nullptr};

  FunctionCallGraphInfo FuncCGInfo;
  const auto &CallSitesInfoMap = MF->getCallSitesInfo();

  // Dangling targets are not mapped to any blocks and must be emitted at the
  // beginning of the function.
  emitDanglingPrefetchTargets();

  const auto &MFPrefetchTargets = MF->getPrefetchTargets();
  for (auto &MBB : *MF) {
    // Print a label for the basic block.
    emitBasicBlockStart(MBB);
    DenseMap<StringRef, unsigned> MnemonicCounts;

    const SmallVector<unsigned> *PrefetchTargets = nullptr;
    if (auto BBID = MBB.getBBID()) {
      auto R = MFPrefetchTargets.find(*BBID);
      if (R != MFPrefetchTargets.end())
        PrefetchTargets = &R->second;
    }
    auto PrefetchTargetIt =
        PrefetchTargets ? PrefetchTargets->begin() : nullptr;
    auto PrefetchTargetEnd = PrefetchTargets ? PrefetchTargets->end() : nullptr;
    unsigned LastCallsiteIndex = 0;

    for (auto &MI : MBB) {
      if (PrefetchTargetIt != PrefetchTargetEnd &&
          *PrefetchTargetIt == LastCallsiteIndex) {
        emitPrefetchTargetSymbol(*MBB.getBBID(), *PrefetchTargetIt);
        ++PrefetchTargetIt;
      }

      // Print the assembly for the instruction.
      if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() &&
          !MI.isDebugInstr()) {
        HasAnyRealCode = true;
      }

      // If there is a pre-instruction symbol, emit a label for it here.
      if (MCSymbol *S = MI.getPreInstrSymbol())
        OutStreamer->emitLabel(S);

      if (MDNode *MD = MI.getPCSections())
        emitPCSectionsLabel(*MF, *MD);

      for (auto &Handler : Handlers)
        Handler->beginInstruction(&MI);

      if (isVerbose())
        emitComments(MI, STI, OutStreamer->getCommentOS());

#ifndef NDEBUG
      MCFragment *OldFragment = OutStreamer->getCurrentFragment();
      size_t OldFragSize = OldFragment->getFixedSize();
#endif

      switch (MI.getOpcode()) {
      case TargetOpcode::CFI_INSTRUCTION:
        emitCFIInstruction(MI);
        break;
      case TargetOpcode::LOCAL_ESCAPE:
        emitFrameAlloc(MI);
        break;
      case TargetOpcode::ANNOTATION_LABEL:
      case TargetOpcode::GC_LABEL:
        OutStreamer->emitLabel(MI.getOperand(0).getMCSymbol());
        break;
      case TargetOpcode::EH_LABEL:
        OutStreamer->AddComment("EH_LABEL");
        OutStreamer->emitLabel(MI.getOperand(0).getMCSymbol());
        // For AsynchEH, insert a Nop if followed by a trap inst
        //   Or the exception won't be caught.
        //   (see MCConstantExpr::create(1,..) in WinException.cpp)
        //  Ignore SDiv/UDiv because a DIV with Const-0 divisor
        //    must have being turned into an UndefValue.
        //  Div with variable opnds won't be the first instruction in
        //  an EH region as it must be led by at least a Load
        {
          auto MI2 = std::next(MI.getIterator());
          if (IsEHa && MI2 != MBB.end() &&
              (MI2->mayLoadOrStore() || MI2->mayRaiseFPException()))
            emitNops(1);
        }
        break;
      case TargetOpcode::INLINEASM:
      case TargetOpcode::INLINEASM_BR:
        emitInlineAsm(&MI);
        break;
      case TargetOpcode::DBG_VALUE:
      case TargetOpcode::DBG_VALUE_LIST:
        if (isVerbose()) {
          if (!emitDebugValueComment(&MI, *this))
            emitInstruction(&MI);
        }
        break;
      case TargetOpcode::DBG_INSTR_REF:
        // This instruction reference will have been resolved to a machine
        // location, and a nearby DBG_VALUE created. We can safely ignore
        // the instruction reference.
        break;
      case TargetOpcode::DBG_PHI:
        // This instruction is only used to label a program point, it's purely
        // meta information.
        break;
      case TargetOpcode::DBG_LABEL:
        if (isVerbose()) {
          if (!emitDebugLabelComment(&MI, *this))
            emitInstruction(&MI);
        }
        break;
      case TargetOpcode::IMPLICIT_DEF:
        if (isVerbose()) emitImplicitDef(&MI);
        break;
      case TargetOpcode::KILL:
        if (isVerbose()) emitKill(&MI, *this);
        break;
      case TargetOpcode::FAKE_USE:
        if (isVerbose())
          emitFakeUse(&MI, *this);
        break;
      case TargetOpcode::PSEUDO_PROBE:
        emitPseudoProbe(MI);
        break;
      case TargetOpcode::ARITH_FENCE:
        if (isVerbose())
          OutStreamer->emitRawComment("ARITH_FENCE");
        break;
      case TargetOpcode::MEMBARRIER:
        OutStreamer->emitRawComment("MEMBARRIER");
        break;
      case TargetOpcode::JUMP_TABLE_DEBUG_INFO:
        // This instruction is only used to note jump table debug info, it's
        // purely meta information.
        break;
      case TargetOpcode::INIT_UNDEF:
        // This is only used to influence register allocation behavior, no
        // actual initialization is needed.
        break;
      case TargetOpcode::RELOC_NONE: {
        // Generate a temporary label for the current PC.
        MCSymbol *Sym = OutContext.createTempSymbol("reloc_none");
        OutStreamer->emitLabel(Sym);
        const MCExpr *Dot = MCSymbolRefExpr::create(Sym, OutContext);
        const MCExpr *Value = MCSymbolRefExpr::create(
            OutContext.getOrCreateSymbol(MI.getOperand(0).getSymbolName()),
            OutContext);
        OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc());
        break;
      }
      default:
        emitInstruction(&MI);

        auto CountInstruction = [&](const MachineInstr &MI) {
          // Skip Meta instructions inside bundles.
          if (MI.isMetaInstruction())
            return;
          ++NumInstsInFunction;
          if (CanDoExtraAnalysis) {
            StringRef Name = getMIMnemonic(MI, *OutStreamer);
            ++MnemonicCounts[Name];
          }
        };
        if (!MI.isBundle()) {
          CountInstruction(MI);
          break;
        }
        // Separately count all the instructions in a bundle.
        for (auto It = std::next(MI.getIterator());
             It != MBB.end() && It->isInsideBundle(); ++It) {
          CountInstruction(*It);
        }
        break;
      }

#ifndef NDEBUG
      // Verify that the instruction size reported by InstrInfo matches the
      // actually emitted size. Many backends performing branch relaxation
      // on the MIR level rely on this for correctness.
      // TODO: We currently can't distinguish whether a parse error occurred
      // when handling INLINEASM.
      if (OutStreamer->isObj() && !OutContext.hadError() &&
          (MI.getOpcode() != TargetOpcode::INLINEASM &&
           MI.getOpcode() != TargetOpcode::INLINEASM_BR)) {
        const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
        TargetInstrInfo::InstSizeVerifyMode Mode =
            TII->getInstSizeVerifyMode(MI);
        if (Mode != TargetInstrInfo::InstSizeVerifyMode::NoVerify) {
          unsigned ExpectedSize = TII->getInstSizeInBytes(MI);
          MCFragment *NewFragment = OutStreamer->getCurrentFragment();
          unsigned ActualSize;
          if (OldFragment == NewFragment) {
            ActualSize = NewFragment->getFixedSize() - OldFragSize;
          } else {
            ActualSize = OldFragment->getFixedSize() - OldFragSize;
            const MCFragment *F = OldFragment->getNext();
            for (; F != NewFragment; F = F->getNext())
              ActualSize += F->getFixedSize();
            ActualSize += NewFragment->getFixedSize();
          }
          bool AllowOverEstimate =
              Mode == TargetInstrInfo::InstSizeVerifyMode::AllowOverEstimate;
          bool Valid = AllowOverEstimate ? ActualSize <= ExpectedSize
                                         : ActualSize == ExpectedSize;
          if (!Valid) {
            dbgs() << "In function: " << MF->getName() << "\n";
            dbgs() << "Size mismatch for: " << MI;
            if (MI.isBundled()) {
              dbgs() << "{\n";
              auto It = MI.getIterator(), End = MBB.instr_end();
              for (++It; It != End && It->isInsideBundle(); ++It)
                dbgs().indent(2) << *It;
              dbgs() << "}\n";
            }
            dbgs() << "Expected " << (AllowOverEstimate ? "maximum" : "exact")
                   << " size: " << ExpectedSize << "\n";
            dbgs() << "Actual size: " << ActualSize << "\n";
            abort();
          }
        }
      }
#endif

      if (MI.isCall()) {
        if (MF->getTarget().Options.BBAddrMap)
          OutStreamer->emitLabel(createCallsiteEndSymbol(MBB));
        LastCallsiteIndex++;
      }

      if (TM.Options.EmitCallGraphSection && MI.isCall())
        handleCallsiteForCallgraph(FuncCGInfo, CallSitesInfoMap, MI);

      // If there is a post-instruction symbol, emit a label for it here.
      if (MCSymbol *S = MI.getPostInstrSymbol()) {
        // Emit the weak symbol attribute used for the prefetch target fallback.
        if (TM.getTargetTriple().isOSBinFormatELF()) {
          MCSymbolELF *ESym = static_cast<MCSymbolELF *>(S);
          if (ESym->getBinding() == ELF::STB_WEAK)
            OutStreamer->emitSymbolAttribute(S, MCSA_Weak);
        }
        OutStreamer->emitLabel(S);
      }

      for (auto &Handler : Handlers)
        Handler->endInstruction();
    }
    // Emit the remaining prefetch targets for this block. This includes
    // nonexisting callsite indexes.
    while (PrefetchTargetIt != PrefetchTargetEnd) {
      emitPrefetchTargetSymbol(*MBB.getBBID(), *PrefetchTargetIt);
      ++PrefetchTargetIt;
    }

    // We must emit temporary symbol for the end of this basic block, if either
    // we have BBLabels enabled or if this basic blocks marks the end of a
    // section.
    if (MF->getTarget().Options.BBAddrMap ||
        (MAI.hasDotTypeDotSizeDirective() && MBB.isEndSection()))
      OutStreamer->emitLabel(MBB.getEndSymbol());

    if (MBB.isEndSection()) {
      // The size directive for the section containing the entry block is
      // handled separately by the function section.
      if (!MBB.sameSection(&MF->front())) {
        if (MAI.hasDotTypeDotSizeDirective()) {
          // Emit the size directive for the basic block section.
          const MCExpr *SizeExp = MCBinaryExpr::createSub(
              MCSymbolRefExpr::create(MBB.getEndSymbol(), OutContext),
              MCSymbolRefExpr::create(CurrentSectionBeginSym, OutContext),
              OutContext);
          OutStreamer->emitELFSize(CurrentSectionBeginSym, SizeExp);
        }
        assert(!MBBSectionRanges.contains(MBB.getSectionID()) &&
               "Overwrite section range");
        MBBSectionRanges[MBB.getSectionID()] =
            MBBSectionRange{CurrentSectionBeginSym, MBB.getEndSymbol()};
      }
    }
    emitBasicBlockEnd(MBB);

    if (CanDoExtraAnalysis) {
      // Skip empty blocks.
      if (MBB.empty())
        continue;

      MachineOptimizationRemarkAnalysis R(DEBUG_TYPE, "InstructionMix",
                                          MBB.begin()->getDebugLoc(), &MBB);

      // Generate instruction mix remark. First, sort counts in descending order
      // by count and name.
      SmallVector<std::pair<StringRef, unsigned>, 128> MnemonicVec;
      for (auto &KV : MnemonicCounts)
        MnemonicVec.emplace_back(KV.first, KV.second);

      sort(MnemonicVec, [](const std::pair<StringRef, unsigned> &A,
                           const std::pair<StringRef, unsigned> &B) {
        if (A.second > B.second)
          return true;
        if (A.second == B.second)
          return StringRef(A.first) < StringRef(B.first);
        return false;
      });
      R << "BasicBlock: " << ore::NV("BasicBlock", MBB.getName()) << "\n";
      for (auto &KV : MnemonicVec) {
        auto Name = (Twine("INST_") + getToken(KV.first.trim()).first).str();
        R << KV.first << ": " << ore::NV(Name, KV.second) << "\n";
      }
      ORE->emit(R);
    }
  }

  EmittedInsts += NumInstsInFunction;
  MachineOptimizationRemarkAnalysis R(DEBUG_TYPE, "InstructionCount",
                                      MF->getFunction().getSubprogram(),
                                      &MF->front());
  R << ore::NV("NumInstructions", NumInstsInFunction)
    << " instructions in function";
  ORE->emit(R);

  // If the function is empty and the object file uses .subsections_via_symbols,
  // then we need to emit *something* to the function body to prevent the
  // labels from collapsing together.  Just emit a noop.
  // Similarly, don't emit empty functions on Windows either. It can lead to
  // duplicate entries (two functions with the same RVA) in the Guard CF Table
  // after linking, causing the kernel not to load the binary:
  // https://developercommunity.visualstudio.com/content/problem/45366/vc-linker-creates-invalid-dll-with-clang-cl.html
  // FIXME: Hide this behind some API in e.g. MCAsmInfo or MCTargetStreamer.
  const Triple &TT = TM.getTargetTriple();
  if (!HasAnyRealCode && (MAI.hasSubsectionsViaSymbols() ||
                          (TT.isOSWindows() && TT.isOSBinFormatCOFF()))) {
    MCInst Noop = MF->getSubtarget().getInstrInfo()->getNop();

    // Targets can opt-out of emitting the noop here by leaving the opcode
    // unspecified.
    if (Noop.getOpcode()) {
      OutStreamer->AddComment("avoids zero-length function");
      emitNops(1);
    }
  }

  // Switch to the original section in case basic block sections was used.
  OutStreamer->switchSection(MF->getSection());

  const Function &F = MF->getFunction();
  for (const auto &BB : F) {
    if (!BB.hasAddressTaken())
      continue;
    MCSymbol *Sym = GetBlockAddressSymbol(&BB);
    if (Sym->isDefined())
      continue;
    OutStreamer->AddComment("Address of block that was removed by CodeGen");
    OutStreamer->emitLabel(Sym);
  }

  // Emit target-specific gunk after the function body.
  emitFunctionBodyEnd();

  // Tail-pad functions that want it.
  if (F.hasFnAttribute("tail-pad-to-size")) {
    auto *FnEndSym = createTempSymbol("tail_pad_start");
    OutStreamer->emitLabel(FnEndSym);

    uint64_t PadToSize = F.getFnAttributeAsParsedInteger("tail-pad-to-size");
    uint64_t FillValue =
        PadToSize ? F.getFnAttributeAsParsedInteger("tail-pad-value") : 0;

    // .fill ((PadToSize - FuncSize) & (PadToSize - FuncSize >= 0)) FillValue
    const MCExpr *FuncSize = MCBinaryExpr::createSub(
        MCSymbolRefExpr::create(FnEndSym, OutContext),
        MCSymbolRefExpr::create(CurrentFnSymForSize, OutContext), OutContext);
    const MCExpr *SizeConst = MCConstantExpr::create(PadToSize, OutContext);
    const MCExpr *Zero = MCConstantExpr::create(0, OutContext);
    const MCExpr *SubExpr =
        MCBinaryExpr::createSub(SizeConst, FuncSize, OutContext);
    const MCExpr *Cmp = MCBinaryExpr::createGTE(SubExpr, Zero, OutContext);
    const MCExpr *FillExpr = MCBinaryExpr::createAnd(SubExpr, Cmp, OutContext);
    OutStreamer->emitFill(*FillExpr, FillValue);
  }

  // Even though wasm supports .type and .size in general, function symbols
  // are automatically sized.
  bool EmitFunctionSize = MAI.hasDotTypeDotSizeDirective() && !TT.isWasm();

  // SPIR-V supports label instructions only inside a block, not after the
  // function body.
  if (TT.getObjectFormat() != Triple::SPIRV &&
      (EmitFunctionSize || needFuncLabels(*MF, *this) || CurrentFnEnd)) {
    // Create a symbol for the end of function, if not already pre-created
    // (e.g. for .prefalign directive).
    if (!CurrentFnEnd)
      CurrentFnEnd = createTempSymbol("func_end");
    OutStreamer->emitLabel(CurrentFnEnd);
  }

  // If the target wants a .size directive for the size of the function, emit
  // it.
  if (EmitFunctionSize) {
    // We can get the size as difference between the function label and the
    // temp label.
    const MCExpr *SizeExp = MCBinaryExpr::createSub(
        MCSymbolRefExpr::create(CurrentFnEnd, OutContext),
        MCSymbolRefExpr::create(CurrentFnSymForSize, OutContext), OutContext);
    OutStreamer->emitELFSize(CurrentFnSym, SizeExp);
    if (CurrentFnBeginLocal)
      OutStreamer->emitELFSize(CurrentFnBeginLocal, SizeExp);
  }

  // Call endBasicBlockSection on the last block now, if it wasn't already
  // called.
  if (!MF->back().isEndSection()) {
    for (auto &Handler : Handlers)
      Handler->endBasicBlockSection(MF->back());
    for (auto &Handler : EHHandlers)
      Handler->endBasicBlockSection(MF->back());
  }
  for (auto &Handler : Handlers)
    Handler->markFunctionEnd();
  for (auto &Handler : EHHandlers)
    Handler->markFunctionEnd();
  // Update the end label of the entry block's section.
  MBBSectionRanges[MF->front().getSectionID()].EndLabel = CurrentFnEnd;

  // Print out jump tables referenced by the function.
  emitJumpTableInfo();

  // Emit post-function debug and/or EH information.
  for (auto &Handler : Handlers)
    Handler->endFunction(MF);
  for (auto &Handler : EHHandlers)
    Handler->endFunction(MF);

  // Emit section containing BB address offsets and their metadata, when
  // BB labels are requested for this function. Skip empty functions.
  if (HasAnyRealCode) {
    if (MF->getTarget().Options.BBAddrMap)
      emitBBAddrMapSection(*MF);
    else if (PgoAnalysisMapFeatures.getBits() != 0)
      MF->getContext().reportWarning(
          SMLoc(), "pgo-analysis-map is enabled for function " + MF->getName() +
                       " but it does not have labels");
  }

  // Emit sections containing instruction and function PCs.
  emitPCSections(*MF);

  // Emit section containing stack size metadata.
  emitStackSizeSection(*MF);

  // Emit section containing call graph metadata.
  emitCallGraphSection(*MF, FuncCGInfo);

  // Emit .su file containing function stack size information.
  emitStackUsage(*MF);

  emitPatchableFunctionEntries();

  if (isVerbose())
    OutStreamer->getCommentOS() << "-- End function\n";

  OutStreamer->addBlankLine();
}

/// Compute the number of Global Variables that uses a Constant.
static unsigned getNumGlobalVariableUses(const Constant *C,
                                         bool &HasNonGlobalUsers) {
  if (!C) {
    HasNonGlobalUsers = true;
    return 0;
  }

  if (isa<GlobalVariable>(C))
    return 1;

  unsigned NumUses = 0;
  for (const auto *CU : C->users())
    NumUses +=
        getNumGlobalVariableUses(dyn_cast<Constant>(CU), HasNonGlobalUsers);

  return NumUses;
}

/// Only consider global GOT equivalents if at least one user is a
/// cstexpr inside an initializer of another global variables. Also, don't
/// handle cstexpr inside instructions. During global variable emission,
/// candidates are skipped and are emitted later in case at least one cstexpr
/// isn't replaced by a PC relative GOT entry access.
static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
                                     unsigned &NumGOTEquivUsers,
                                     bool &HasNonGlobalUsers) {
  // Global GOT equivalents are unnamed private globals with a constant
  // pointer initializer to another global symbol. They must point to a
  // GlobalVariable or Function, i.e., as GlobalValue.
  if (!GV->hasGlobalUnnamedAddr() || !GV->hasInitializer() ||
      !GV->isConstant() || !GV->isDiscardableIfUnused() ||
      !isa<GlobalValue>(GV->getOperand(0)))
    return false;

  // To be a got equivalent, at least one of its users need to be a constant
  // expression used by another global variable.
  for (const auto *U : GV->users())
    NumGOTEquivUsers +=
        getNumGlobalVariableUses(dyn_cast<Constant>(U), HasNonGlobalUsers);

  return NumGOTEquivUsers > 0;
}

/// Unnamed constant global variables solely contaning a pointer to
/// another globals variable is equivalent to a GOT table entry; it contains the
/// the address of another symbol. Optimize it and replace accesses to these
/// "GOT equivalents" by using the GOT entry for the final global instead.
/// Compute GOT equivalent candidates among all global variables to avoid
/// emitting them if possible later on, after it use is replaced by a GOT entry
/// access.
void AsmPrinter::computeGlobalGOTEquivs(Module &M) {
  if (!getObjFileLowering().supportIndirectSymViaGOTPCRel())
    return;

  for (const auto &G : M.globals()) {
    unsigned NumGOTEquivUsers = 0;
    bool HasNonGlobalUsers = false;
    if (!isGOTEquivalentCandidate(&G, NumGOTEquivUsers, HasNonGlobalUsers))
      continue;
    // If non-global variables use it, we still need to emit it.
    // Add 1 here, then emit it in `emitGlobalGOTEquivs`.
    if (HasNonGlobalUsers)
      NumGOTEquivUsers += 1;
    const MCSymbol *GOTEquivSym = getSymbol(&G);
    GlobalGOTEquivs[GOTEquivSym] = std::make_pair(&G, NumGOTEquivUsers);
  }
}

/// Constant expressions using GOT equivalent globals may not be eligible
/// for PC relative GOT entry conversion, in such cases we need to emit such
/// globals we previously omitted in EmitGlobalVariable.
void AsmPrinter::emitGlobalGOTEquivs() {
  if (!getObjFileLowering().supportIndirectSymViaGOTPCRel())
    return;

  SmallVector<const GlobalVariable *, 8> FailedCandidates;
  for (auto &I : GlobalGOTEquivs) {
    const GlobalVariable *GV = I.second.first;
    unsigned Cnt = I.second.second;
    if (Cnt)
      FailedCandidates.push_back(GV);
  }
  GlobalGOTEquivs.clear();

  for (const auto *GV : FailedCandidates)
    emitGlobalVariable(GV);
}

void AsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) {
  MCSymbol *Name = getSymbol(&GA);
  const GlobalObject *BaseObject = GA.getAliaseeObject();

  bool IsFunction = GA.getValueType()->isFunctionTy();
  // Treat bitcasts of functions as functions also. This is important at least
  // on WebAssembly where object and function addresses can't alias each other.
  if (!IsFunction)
    IsFunction = isa_and_nonnull<Function>(BaseObject);

  // AIX's assembly directive `.set` is not usable for aliasing purpose,
  // so AIX has to use the extra-label-at-definition strategy. At this
  // point, all the extra label is emitted, we just have to emit linkage for
  // those labels.
  if (TM.getTargetTriple().isOSBinFormatXCOFF()) {
    // Linkage for alias of global variable has been emitted.
    if (isa_and_nonnull<GlobalVariable>(BaseObject))
      return;

    emitLinkage(&GA, Name);
    // If it's a function, also emit linkage for aliases of function entry
    // point.
    if (IsFunction)
      emitLinkage(&GA,
                  getObjFileLowering().getFunctionEntryPointSymbol(&GA, TM));
    return;
  }

  if (GA.hasExternalLinkage() || !MAI.getWeakRefDirective())
    OutStreamer->emitSymbolAttribute(Name, MCSA_Global);
  else if (GA.hasWeakLinkage() || GA.hasLinkOnceLinkage())
    OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference);
  else
    assert(GA.hasLocalLinkage() && "Invalid alias linkage");

  // Set the symbol type to function if the alias has a function type.
  // This affects codegen when the aliasee is not a function.
  if (IsFunction) {
    OutStreamer->emitSymbolAttribute(Name, MCSA_ELF_TypeFunction);
    if (TM.getTargetTriple().isOSBinFormatCOFF()) {
      OutStreamer->beginCOFFSymbolDef(Name);
      OutStreamer->emitCOFFSymbolStorageClass(
          GA.hasLocalLinkage() ? COFF::IMAGE_SYM_CLASS_STATIC
                               : COFF::IMAGE_SYM_CLASS_EXTERNAL);
      OutStreamer->emitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
                                      << COFF::SCT_COMPLEX_TYPE_SHIFT);
      OutStreamer->endCOFFSymbolDef();
    }
  }

  emitVisibility(Name, GA.getVisibility());

  const MCExpr *Expr = lowerConstant(GA.getAliasee());

  if (MAI.isMachO() && isa<MCBinaryExpr>(Expr))
    OutStreamer->emitSymbolAttribute(Name, MCSA_AltEntry);

  // Emit the directives as assignments aka .set:
  OutStreamer->emitAssignment(Name, Expr);
  MCSymbol *LocalAlias = getSymbolPreferLocal(GA);
  if (LocalAlias != Name)
    OutStreamer->emitAssignment(LocalAlias, Expr);

  // If the aliasee does not correspond to a symbol in the output, i.e. the
  // alias is not of an object or the aliased object is private, then set the
  // size of the alias symbol from the type of the alias. We don't do this in
  // other situations as the alias and aliasee having differing types but same
  // size may be intentional.
  if (MAI.hasDotTypeDotSizeDirective() && GA.getValueType()->isSized() &&
      (!BaseObject || BaseObject->hasPrivateLinkage())) {
    const DataLayout &DL = M.getDataLayout();
    uint64_t Size = DL.getTypeAllocSize(GA.getValueType());
    OutStreamer->emitELFSize(Name, MCConstantExpr::create(Size, OutContext));
  }
}

void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
  auto EmitLinkage = [&](MCSymbol *Sym) {
    if (GI.hasExternalLinkage() || !MAI.getWeakRefDirective())
      OutStreamer->emitSymbolAttribute(Sym, MCSA_Global);
    else if (GI.hasWeakLinkage() || GI.hasLinkOnceLinkage())
      OutStreamer->emitSymbolAttribute(Sym, MCSA_WeakReference);
    else
      assert(GI.hasLocalLinkage() && "Invalid ifunc linkage");
  };

  if (TM.getTargetTriple().isOSBinFormatELF()) {
    MCSymbol *Name = getSymbol(&GI);
    EmitLinkage(Name);
    OutStreamer->emitSymbolAttribute(Name, MCSA_ELF_TypeIndFunction);
    emitVisibility(Name, GI.getVisibility());

    // Emit the directives as assignments aka .set:
    const MCExpr *Expr = lowerConstant(GI.getResolver());
    OutStreamer->emitAssignment(Name, Expr);
    MCSymbol *LocalAlias = getSymbolPreferLocal(GI);
    if (LocalAlias != Name)
      OutStreamer->emitAssignment(LocalAlias, Expr);

    return;
  }

  if (!TM.getTargetTriple().isOSBinFormatMachO() || !getIFuncMCSubtargetInfo())
    reportFatalUsageError("IFuncs are not supported on this platform");

  // On Darwin platforms, emit a manually-constructed .symbol_resolver that
  // implements the symbol resolution duties of the IFunc.
  //
  // Normally, this would be handled by linker magic, but unfortunately there
  // are a few limitations in ld64 and ld-prime's implementation of
  // .symbol_resolver that mean we can't always use them:
  //
  //    *  resolvers cannot be the target of an alias
  //    *  resolvers cannot have private linkage
  //    *  resolvers cannot have linkonce linkage
  //    *  resolvers cannot appear in executables
  //    *  resolvers cannot appear in bundles
  //
  // This works around that by emitting a close approximation of what the
  // linker would have done.

  MCSymbol *LazyPointer =
      GetExternalSymbolSymbol(GI.getName() + ".lazy_pointer");
  MCSymbol *StubHelper = GetExternalSymbolSymbol(GI.getName() + ".stub_helper");

  OutStreamer->switchSection(OutContext.getObjectFileInfo()->getDataSection());

  const DataLayout &DL = M.getDataLayout();
  emitAlignment(Align(DL.getPointerSize()));
  OutStreamer->emitLabel(LazyPointer);
  emitVisibility(LazyPointer, GI.getVisibility());
  OutStreamer->emitValue(MCSymbolRefExpr::create(StubHelper, OutContext), 8);

  OutStreamer->switchSection(OutContext.getObjectFileInfo()->getTextSection());

  const TargetSubtargetInfo *STI =
      TM.getSubtargetImpl(*GI.getResolverFunction());
  const TargetLowering *TLI = STI->getTargetLowering();
  Align TextAlign(TLI->getMinFunctionAlignment());

  MCSymbol *Stub = getSymbol(&GI);
  EmitLinkage(Stub);
  OutStreamer->emitCodeAlignment(TextAlign, *getIFuncMCSubtargetInfo());
  OutStreamer->emitLabel(Stub);
  emitVisibility(Stub, GI.getVisibility());
  emitMachOIFuncStubBody(M, GI, LazyPointer);

  OutStreamer->emitCodeAlignment(TextAlign, *getIFuncMCSubtargetInfo());
  OutStreamer->emitLabel(StubHelper);
  emitVisibility(StubHelper, GI.getVisibility());
  emitMachOIFuncStubHelperBody(M, GI, LazyPointer);
}

void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) {
  if (!RS.wantsSection())
    return;
  if (!RS.getFilename())
    return;

  MCSection *RemarksSection =
      OutContext.getObjectFileInfo()->getRemarksSection();
  if (!RemarksSection && RS.needsSection()) {
    OutContext.reportWarning(SMLoc(), "Current object file format does not "
                                      "support remarks sections.");
  }
  if (!RemarksSection)
    return;

  SmallString<128> Filename = *RS.getFilename();
  sys::fs::make_absolute(Filename);
  assert(!Filename.empty() && "The filename can't be empty.");

  std::string Buf;
  raw_string_ostream OS(Buf);

  remarks::RemarkSerializer &RemarkSerializer = RS.getSerializer();
  std::unique_ptr<remarks::MetaSerializer> MetaSerializer =
      RemarkSerializer.metaSerializer(OS, Filename);
  MetaSerializer->emit();

  // Switch to the remarks section.
  OutStreamer->switchSection(RemarksSection);
  OutStreamer->emitBinaryData(Buf);
}

static uint64_t globalSize(const llvm::GlobalVariable &G) {
  const Constant *Initializer = G.getInitializer();
  return G.getParent()->getDataLayout().getTypeAllocSize(
      Initializer->getType());
}

static bool shouldTagGlobal(const llvm::GlobalVariable &G) {
  // We used to do this in clang, but there are optimization passes that turn
  // non-constant globals into constants. So now, clang only tells us whether
  // it would *like* a global to be tagged, but we still make the decision here.
  //
  // For now, don't instrument constant data, as it'll be in .rodata anyway. It
  // may be worth instrumenting these in future to stop them from being used as
  // gadgets.
  if (G.getName().starts_with("llvm.") || G.isThreadLocal() || G.isConstant())
    return false;

  // Globals can be placed implicitly or explicitly in sections. There's two
  // different types of globals that meet this criteria that cause problems:
  //  1. Function pointers that are going into various init arrays (either
  //     explicitly through `__attribute__((section(<foo>)))` or implicitly
  //     through `__attribute__((constructor)))`, such as ".(pre)init(_array)",
  //     ".fini(_array)", ".ctors", and ".dtors". These function pointers end up
  //     overaligned and overpadded, making iterating over them problematic, and
  //     each function pointer is individually tagged (so the iteration over
  //     them causes SIGSEGV/MTE[AS]ERR).
  //  2. Global variables put into an explicit section, where the section's name
  //     is a valid C-style identifier. The linker emits a `__start_<name>` and
  //     `__stop_<name>` symbol for the section, so that you can iterate over
  //     globals within this section. Unfortunately, again, these globals would
  //     be tagged and so iteration causes SIGSEGV/MTE[AS]ERR.
  //
  // To mitigate both these cases, and because specifying a section is rare
  // outside of these two cases, disable MTE protection for globals in any
  // section.
  if (G.hasSection())
    return false;

  return globalSize(G) > 0;
}

static void tagGlobalDefinition(Module &M, GlobalVariable *G) {
  uint64_t SizeInBytes = globalSize(*G);

  uint64_t NewSize = alignTo(SizeInBytes, 16);
  if (SizeInBytes != NewSize) {
    // Pad the initializer out to the next multiple of 16 bytes.
    llvm::SmallVector<uint8_t> Init(NewSize - SizeInBytes, 0);
    Constant *Padding = ConstantDataArray::get(M.getContext(), Init);
    Constant *Initializer = G->getInitializer();
    Initializer = ConstantStruct::getAnon({Initializer, Padding});
    auto *NewGV = new GlobalVariable(
        M, Initializer->getType(), G->isConstant(), G->getLinkage(),
        Initializer, "", G, G->getThreadLocalMode(), G->getAddressSpace());
    NewGV->copyAttributesFrom(G);
    NewGV->setComdat(G->getComdat());
    NewGV->copyMetadata(G, 0);

    NewGV->takeName(G);
    G->replaceAllUsesWith(NewGV);
    G->eraseFromParent();
    G = NewGV;
  }

  if (G->getAlign().valueOrOne() < 16)
    G->setAlignment(Align(16));

  // Ensure that tagged globals don't get merged by ICF - as they should have
  // different tags at runtime.
  G->setUnnamedAddr(GlobalValue::UnnamedAddr::None);
}

static void removeMemtagFromGlobal(GlobalVariable &G) {
  auto Meta = G.getSanitizerMetadata();
  Meta.Memtag = false;
  G.setSanitizerMetadata(Meta);
}

bool AsmPrinter::doFinalization(Module &M) {
  // Set the MachineFunction to nullptr so that we can catch attempted
  // accesses to MF specific features at the module level and so that
  // we can conditionalize accesses based on whether or not it is nullptr.
  MF = nullptr;
  const Triple &Target = TM.getTargetTriple();

  std::vector<GlobalVariable *> GlobalsToTag;
  for (GlobalVariable &G : M.globals()) {
    if (G.isDeclaration() || !G.isTagged())
      continue;
    if (!shouldTagGlobal(G)) {
      assert(G.hasSanitizerMetadata()); // because isTagged.
      removeMemtagFromGlobal(G);
      assert(!G.isTagged());
      continue;
    }
    GlobalsToTag.push_back(&G);
  }
  for (GlobalVariable *G : GlobalsToTag)
    tagGlobalDefinition(M, G);

  // Gather all GOT equivalent globals in the module. We really need two
  // passes over the globals: one to compute and another to avoid its emission
  // in EmitGlobalVariable, otherwise we would not be able to handle cases
  // where the got equivalent shows up before its use.
  computeGlobalGOTEquivs(M);

  // Emit global variables.
  for (const auto &G : M.globals())
    emitGlobalVariable(&G);

  // Emit remaining GOT equivalent globals.
  emitGlobalGOTEquivs();

  const TargetLoweringObjectFile &TLOF = getObjFileLowering();

  // Emit linkage(XCOFF) and visibility info for declarations
  for (const Function &F : M) {
    if (!F.isDeclarationForLinker())
      continue;

    MCSymbol *Name = getSymbol(&F);
    // Function getSymbol gives us the function descriptor symbol for XCOFF.

    if (!Target.isOSBinFormatXCOFF()) {
      GlobalValue::VisibilityTypes V = F.getVisibility();
      if (V == GlobalValue::DefaultVisibility)
        continue;

      emitVisibility(Name, V, false);
      continue;
    }

    if (F.isIntrinsic())
      continue;

    // Handle the XCOFF case.
    // Variable `Name` is the function descriptor symbol (see above). Get the
    // function entry point symbol.
    MCSymbol *FnEntryPointSym = TLOF.getFunctionEntryPointSymbol(&F, TM);
    // Emit linkage for the function entry point.
    emitLinkage(&F, FnEntryPointSym);

    // If a function's address is taken, which means it may be called via a
    // function pointer, we need the function descriptor for it.
    if (F.hasAddressTaken())
      emitLinkage(&F, Name);
  }

  // Emit the remarks section contents.
  // FIXME: Figure out when is the safest time to emit this section. It should
  // not come after debug info.
  if (remarks::RemarkStreamer *RS = M.getContext().getMainRemarkStreamer())
    emitRemarksSection(*RS);

  TLOF.emitModuleMetadata(*OutStreamer, M);

  if (Target.isOSBinFormatELF()) {
    MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();

    // Output stubs for external and common global variables.
    MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
    if (!Stubs.empty()) {
      OutStreamer->switchSection(TLOF.getDataSection());
      const DataLayout &DL = M.getDataLayout();

      emitAlignment(Align(DL.getPointerSize()));
      for (const auto &Stub : Stubs) {
        OutStreamer->emitLabel(Stub.first);
        OutStreamer->emitSymbolValue(Stub.second.getPointer(),
                                     DL.getPointerSize());
      }
    }
  }

  if (Target.isOSBinFormatCOFF()) {
    MachineModuleInfoCOFF &MMICOFF =
        MMI->getObjFileInfo<MachineModuleInfoCOFF>();

    // Output stubs for external and common global variables.
    MachineModuleInfoCOFF::SymbolListTy Stubs = MMICOFF.GetGVStubList();
    if (!Stubs.empty()) {
      const DataLayout &DL = M.getDataLayout();

      for (const auto &Stub : Stubs) {
        SmallString<256> SectionName = StringRef(".rdata$");
        SectionName += Stub.first->getName();
        OutStreamer->switchSection(OutContext.getCOFFSection(
            SectionName,
            COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
                COFF::IMAGE_SCN_LNK_COMDAT,
            Stub.first->getName(), COFF::IMAGE_COMDAT_SELECT_ANY));
        emitAlignment(Align(DL.getPointerSize()));
        OutStreamer->emitSymbolAttribute(Stub.first, MCSA_Global);
        OutStreamer->emitLabel(Stub.first);
        OutStreamer->emitSymbolValue(Stub.second.getPointer(),
                                     DL.getPointerSize());
      }
    }
  }

  // This needs to happen before emitting debug information since that can end
  // arbitrary sections.
  if (auto *TS = OutStreamer->getTargetStreamer())
    TS->emitConstantPools();

  // Emit Stack maps before any debug info. Mach-O requires that no data or
  // text sections come after debug info has been emitted. This matters for
  // stack maps as they are arbitrary data, and may even have a custom format
  // through user plugins.
  EmitStackMaps(M);

  // Print aliases in topological order, that is, for each alias a = b,
  // b must be printed before a.
  // This is because on some targets (e.g. PowerPC) linker expects aliases in
  // such an order to generate correct TOC information.
  SmallVector<const GlobalAlias *, 16> AliasStack;
  SmallPtrSet<const GlobalAlias *, 16> AliasVisited;
  for (const auto &Alias : M.aliases()) {
    if (Alias.hasAvailableExternallyLinkage())
      continue;
    for (const GlobalAlias *Cur = &Alias; Cur;
         Cur = dyn_cast<GlobalAlias>(Cur->getAliasee())) {
      if (!AliasVisited.insert(Cur).second)
        break;
      AliasStack.push_back(Cur);
    }
    for (const GlobalAlias *AncestorAlias : llvm::reverse(AliasStack))
      emitGlobalAlias(M, *AncestorAlias);
    AliasStack.clear();
  }

  // IFuncs must come before deubginfo in case the backend decides to emit them
  // as actual functions, since on Mach-O targets, we cannot create regular
  // sections after DWARF.
  for (const auto &IFunc : M.ifuncs())
    emitGlobalIFunc(M, IFunc);
  if (TM.getTargetTriple().isOSBinFormatXCOFF() && hasDebugInfo()) {
    // Emit section end. This is used to tell the debug line section where the
    // end is for a text section if we don't use .loc to represent the debug
    // line.
    auto *Sec = OutContext.getObjectFileInfo()->getTextSection();
    OutStreamer->switchSectionNoPrint(Sec);
    MCSymbol *Sym = Sec->getEndSymbol(OutContext);
    OutStreamer->emitLabel(Sym);
  }

  // Finalize debug and EH information.
  for (auto &Handler : Handlers)
    Handler->endModule();
  for (auto &Handler : EHHandlers)
    Handler->endModule();

  // This deletes all the ephemeral handlers that AsmPrinter added, while
  // keeping all the user-added handlers alive until the AsmPrinter is
  // destroyed.
  EHHandlers.clear();
  Handlers.erase(Handlers.begin() + NumUserHandlers, Handlers.end());
  DD = nullptr;

  // If the target wants to know about weak references, print them all.
  if (MAI.getWeakRefDirective()) {
    // FIXME: This is not lazy, it would be nice to only print weak references
    // to stuff that is actually used.  Note that doing so would require targets
    // to notice uses in operands (due to constant exprs etc).  This should
    // happen with the MC stuff eventually.

    // Print out module-level global objects here.
    for (const auto &GO : M.global_objects()) {
      if (!GO.hasExternalWeakLinkage())
        continue;
      OutStreamer->emitSymbolAttribute(getSymbol(&GO), MCSA_WeakReference);
    }
    if (shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()) {
      auto SymbolName = "swift_async_extendedFramePointerFlags";
      auto Global = M.getGlobalVariable(SymbolName);
      if (!Global) {
        auto PtrTy = PointerType::getUnqual(M.getContext());
        Global = new GlobalVariable(M, PtrTy, false,
                                    GlobalValue::ExternalWeakLinkage, nullptr,
                                    SymbolName);
        OutStreamer->emitSymbolAttribute(getSymbol(Global), MCSA_WeakReference);
      }
    }
  }

  FinishGCAssembly(M);

  // Emit llvm.ident metadata in an '.ident' directive.
  emitModuleIdents(M);

  // Emit bytes for llvm.commandline metadata.
  // The command line metadata is emitted earlier on XCOFF.
  if (!Target.isOSBinFormatXCOFF())
    emitModuleCommandLines(M);

  // Emit .note.GNU-split-stack and .note.GNU-no-split-stack sections if
  // split-stack is used.
  if (TM.getTargetTriple().isOSBinFormatELF() && HasSplitStack) {
    OutStreamer->switchSection(OutContext.getELFSection(".note.GNU-split-stack",
                                                        ELF::SHT_PROGBITS, 0));
    if (HasNoSplitStack)
      OutStreamer->switchSection(OutContext.getELFSection(
          ".note.GNU-no-split-stack", ELF::SHT_PROGBITS, 0));
  }

  // If we don't have any trampolines, then we don't require stack memory
  // to be executable. Some targets have a directive to declare this.
  Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
  bool HasTrampolineUses =
      InitTrampolineIntrinsic && !InitTrampolineIntrinsic->use_empty();
  MCSection *S = MAI.getStackSection(OutContext, /*Exec=*/HasTrampolineUses);
  if (S)
    OutStreamer->switchSection(S);

  if (TM.Options.EmitAddrsig) {
    // Emit address-significance attributes for all globals.
    OutStreamer->emitAddrsig();
    for (const GlobalValue &GV : M.global_values()) {
      if (!GV.use_empty() && !GV.isThreadLocal() &&
          !GV.hasDLLImportStorageClass() &&
          !GV.getName().starts_with("llvm.") &&
          !GV.hasAtLeastLocalUnnamedAddr())
        OutStreamer->emitAddrsigSym(getSymbol(&GV));
    }
  }

  // Emit symbol partition specifications (ELF only).
  if (Target.isOSBinFormatELF()) {
    unsigned UniqueID = 0;
    for (const GlobalValue &GV : M.global_values()) {
      if (!GV.hasPartition() || GV.isDeclarationForLinker() ||
          GV.getVisibility() != GlobalValue::DefaultVisibility)
        continue;

      OutStreamer->switchSection(
          OutContext.getELFSection(".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0,
                                   "", false, ++UniqueID, nullptr));
      OutStreamer->emitBytes(GV.getPartition());
      OutStreamer->emitZeros(1);
      OutStreamer->emitValue(
          MCSymbolRefExpr::create(getSymbol(&GV), OutContext),
          MAI.getCodePointerSize());
    }
  }

  // Allow the target to emit any magic that it wants at the end of the file,
  // after everything else has gone out.
  emitEndOfAsmFile(M);

  MMI = nullptr;
  AddrLabelSymbols = nullptr;

  OutStreamer->finish();
  OutStreamer->reset();
  OwnedMLI.reset();
  OwnedMDT.reset();

  return false;
}

MCSymbol *AsmPrinter::getMBBExceptionSym(const MachineBasicBlock &MBB) {
  auto Res = MBBSectionExceptionSyms.try_emplace(MBB.getSectionID());
  if (Res.second)
    Res.first->second = createTempSymbol("exception");
  return Res.first->second;
}

MCSymbol *AsmPrinter::createCallsiteEndSymbol(const MachineBasicBlock &MBB) {
  MCContext &Ctx = MF->getContext();
  MCSymbol *Sym = Ctx.createTempSymbol("BB" + Twine(MF->getFunctionNumber()) +
                                       "_" + Twine(MBB.getNumber()) + "_CS");
  CurrentFnCallsiteEndSymbols[&MBB].push_back(Sym);
  return Sym;
}

void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
  this->MF = &MF;
  const Function &F = MF.getFunction();

  // Record that there are split-stack functions, so we will emit a special
  // section to tell the linker.
  if (MF.shouldSplitStack()) {
    HasSplitStack = true;

    if (!MF.getFrameInfo().needsSplitStackProlog())
      HasNoSplitStack = true;
  } else
    HasNoSplitStack = true;

  // Get the function symbol.
  if (!MAI.isAIX()) {
    CurrentFnSym = getSymbol(&MF.getFunction());
  } else {
    assert(TM.getTargetTriple().isOSAIX() &&
           "Only AIX uses the function descriptor hooks.");
    // AIX is unique here in that the name of the symbol emitted for the
    // function body does not have the same name as the source function's
    // C-linkage name.
    assert(CurrentFnDescSym && "The function descriptor symbol needs to be"
                               " initalized first.");

    // Get the function entry point symbol.
    CurrentFnSym = getObjFileLowering().getFunctionEntryPointSymbol(&F, TM);
  }

  CurrentFnSymForSize = CurrentFnSym;
  CurrentFnBegin = nullptr;
  CurrentFnBeginLocal = nullptr;
  CurrentFnEnd = nullptr;
  CurrentSectionBeginSym = nullptr;
  CurrentFnCallsiteEndSymbols.clear();
  MBBSectionRanges.clear();
  MBBSectionExceptionSyms.clear();
  bool NeedsLocalForSize = MAI.needsLocalForSize();
  if (F.hasFnAttribute("patchable-function-entry") ||
      F.hasFnAttribute("tail-pad-to-size") ||
      F.hasFnAttribute("function-instrument") ||
      F.hasFnAttribute("xray-instruction-threshold") ||
      needFuncLabels(MF, *this) || NeedsLocalForSize ||
      MF.getTarget().Options.EmitStackSizeSection ||
      MF.getTarget().Options.EmitCallGraphSection ||
      MF.getTarget().Options.BBAddrMap) {
    CurrentFnBegin = createTempSymbol("func_begin");
    if (NeedsLocalForSize)
      CurrentFnSymForSize = CurrentFnBegin;
  }

  ORE = GetORE(MF);
}

namespace {

// Keep track the alignment, constpool entries per Section.
  struct SectionCPs {
    MCSection *S;
    Align Alignment;
    SmallVector<unsigned, 4> CPEs;

    SectionCPs(MCSection *s, Align a) : S(s), Alignment(a) {}
  };

} // end anonymous namespace

StringRef AsmPrinter::getConstantSectionSuffix(const Constant *C) const {
  if (TM.Options.EnableStaticDataPartitioning && C && SDPI && PSI)
    return SDPI->getConstantSectionPrefix(C, PSI);

  return "";
}

/// EmitConstantPool - Print to the current output stream assembly
/// representations of the constants in the constant pool MCP. This is
/// used to print out constants which have been "spilled to memory" by
/// the code generator.
void AsmPrinter::emitConstantPool() {
  const MachineConstantPool *MCP = MF->getConstantPool();
  const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
  if (CP.empty()) return;

  // Calculate sections for constant pool entries. We collect entries to go into
  // the same section together to reduce amount of section switch statements.
  SmallVector<SectionCPs, 4> CPSections;
  for (unsigned i = 0, e = CP.size(); i != e; ++i) {
    const MachineConstantPoolEntry &CPE = CP[i];
    Align Alignment = CPE.getAlign();

    SectionKind Kind = CPE.getSectionKind(&getDataLayout());

    const Constant *C = nullptr;
    if (!CPE.isMachineConstantPoolEntry())
      C = CPE.Val.ConstVal;

    MCSection *S = getObjFileLowering().getSectionForConstant(
        getDataLayout(), Kind, C, Alignment, &MF->getFunction(),
        getConstantSectionSuffix(C));

    // The number of sections are small, just do a linear search from the
    // last section to the first.
    bool Found = false;
    unsigned SecIdx = CPSections.size();
    while (SecIdx != 0) {
      if (CPSections[--SecIdx].S == S) {
        Found = true;
        break;
      }
    }
    if (!Found) {
      SecIdx = CPSections.size();
      CPSections.push_back(SectionCPs(S, Alignment));
    }

    if (Alignment > CPSections[SecIdx].Alignment)
      CPSections[SecIdx].Alignment = Alignment;
    CPSections[SecIdx].CPEs.push_back(i);
  }

  // Now print stuff into the calculated sections.
  const MCSection *CurSection = nullptr;
  unsigned Offset = 0;
  for (const SectionCPs &CPSection : CPSections) {
    for (unsigned CPI : CPSection.CPEs) {
      MCSymbol *Sym = GetCPISymbol(CPI);
      if (!Sym->isUndefined())
        continue;

      if (CurSection != CPSection.S) {
        OutStreamer->switchSection(CPSection.S);
        emitAlignment(Align(CPSection.Alignment));
        CurSection = CPSection.S;
        Offset = 0;
      }

      MachineConstantPoolEntry CPE = CP[CPI];

      // Emit inter-object padding for alignment.
      unsigned NewOffset = alignTo(Offset, CPE.getAlign());
      OutStreamer->emitZeros(NewOffset - Offset);

      if (MAI.hasDotTypeDotSizeDirective())
        OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
      OutStreamer->emitLabel(Sym);

      if (CPE.isMachineConstantPoolEntry())
        emitMachineConstantPoolValue(CPE.Val.MachineCPVal);
      else
        emitGlobalConstant(getDataLayout(), CPE.Val.ConstVal);

      unsigned EntrySize = CPE.getSizeInBytes(getDataLayout());
      if (MAI.hasDotTypeDotSizeDirective())
        OutStreamer->emitELFSize(Sym,
                                 MCConstantExpr::create(EntrySize, OutContext));

      Offset = NewOffset + EntrySize;
    }
  }
}

// Print assembly representations of the jump tables used by the current
// function.
void AsmPrinter::emitJumpTableInfo() {
  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
  if (!MJTI) return;

  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
  if (JT.empty()) return;

  if (!TM.Options.EnableStaticDataPartitioning) {
    emitJumpTableImpl(*MJTI, llvm::to_vector(llvm::seq<unsigned>(JT.size())));
    return;
  }

  SmallVector<unsigned> HotJumpTableIndices, ColdJumpTableIndices;
  // When static data partitioning is enabled, collect jump table entries that
  // go into the same section together to reduce the amount of section switch
  // statements.
  for (unsigned JTI = 0, JTSize = JT.size(); JTI < JTSize; ++JTI) {
    if (JT[JTI].Hotness == MachineFunctionDataHotness::Cold) {
      ColdJumpTableIndices.push_back(JTI);
    } else {
      HotJumpTableIndices.push_back(JTI);
    }
  }

  emitJumpTableImpl(*MJTI, HotJumpTableIndices);
  emitJumpTableImpl(*MJTI, ColdJumpTableIndices);
}

void AsmPrinter::emitJumpTableImpl(const MachineJumpTableInfo &MJTI,
                                   ArrayRef<unsigned> JumpTableIndices) {
  if (MJTI.getEntryKind() == MachineJumpTableInfo::EK_Inline ||
      JumpTableIndices.empty())
    return;

  const TargetLoweringObjectFile &TLOF = getObjFileLowering();
  const Function &F = MF->getFunction();
  const std::vector<MachineJumpTableEntry> &JT = MJTI.getJumpTables();
  MCSection *JumpTableSection = nullptr;

  const bool UseLabelDifference =
      MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 ||
      MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference64;
  // Pick the directive to use to print the jump table entries, and switch to
  // the appropriate section.
  const bool JTInDiffSection =
      !TLOF.shouldPutJumpTableInFunctionSection(UseLabelDifference, F);
  if (JTInDiffSection) {
    if (TM.Options.EnableStaticDataPartitioning) {
      JumpTableSection =
          TLOF.getSectionForJumpTable(F, TM, &JT[JumpTableIndices.front()]);
    } else {
      JumpTableSection = TLOF.getSectionForJumpTable(F, TM);
    }
    OutStreamer->switchSection(JumpTableSection);
  }

  const DataLayout &DL = MF->getDataLayout();
  emitAlignment(Align(MJTI.getEntryAlignment(DL)));

  // Jump tables in code sections are marked with a data_region directive
  // where that's supported.
  if (!JTInDiffSection)
    OutStreamer->emitDataRegion(MCDR_DataRegionJT32);

  for (const unsigned JumpTableIndex : JumpTableIndices) {
    ArrayRef<MachineBasicBlock *> JTBBs = JT[JumpTableIndex].MBBs;

    // If this jump table was deleted, ignore it.
    if (JTBBs.empty())
      continue;

    // For the EK_LabelDifference32 entry, if using .set avoids a relocation,
    /// emit a .set directive for each unique entry.
    if (MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
        MAI.doesSetDirectiveSuppressReloc()) {
      SmallPtrSet<const MachineBasicBlock *, 16> EmittedSets;
      const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
      const MCExpr *Base =
          TLI->getPICJumpTableRelocBaseExpr(MF, JumpTableIndex, OutContext);
      for (const MachineBasicBlock *MBB : JTBBs) {
        if (!EmittedSets.insert(MBB).second)
          continue;

        // .set LJTSet, LBB32-base
        const MCExpr *LHS =
            MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
        OutStreamer->emitAssignment(
            GetJTSetSymbol(JumpTableIndex, MBB->getNumber()),
            MCBinaryExpr::createSub(LHS, Base, OutContext));
      }
    }

    // On some targets (e.g. Darwin) we want to emit two consecutive labels
    // before each jump table.  The first label is never referenced, but tells
    // the assembler and linker the extents of the jump table object.  The
    // second label is actually referenced by the code.
    if (JTInDiffSection && DL.hasLinkerPrivateGlobalPrefix())
      // FIXME: This doesn't have to have any specific name, just any randomly
      // named and numbered local label started with 'l' would work.  Simplify
      // GetJTISymbol.
      OutStreamer->emitLabel(GetJTISymbol(JumpTableIndex, true));

    MCSymbol *JTISymbol = GetJTISymbol(JumpTableIndex);
    if (JTInDiffSection && MAI.hasDotTypeDotSizeDirective())
      OutStreamer->emitSymbolAttribute(JTISymbol, MCSA_ELF_TypeObject);
    OutStreamer->emitLabel(JTISymbol);

    // Defer MCAssembler based constant folding due to a performance issue. The
    // label differences will be evaluated at write time.
    for (const MachineBasicBlock *MBB : JTBBs)
      emitJumpTableEntry(MJTI, MBB, JumpTableIndex);

    if (JTInDiffSection && MAI.hasDotTypeDotSizeDirective())
      OutStreamer->emitELFSize(
          JTISymbol, MCConstantExpr::create(
                         JTBBs.size() * MJTI.getEntrySize(DL), OutContext));
  }

  if (EmitJumpTableSizesSection)
    emitJumpTableSizesSection(MJTI, MF->getFunction());

  if (!JTInDiffSection)
    OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
}

void AsmPrinter::emitJumpTableSizesSection(const MachineJumpTableInfo &MJTI,
                                           const Function &F) const {
  const std::vector<MachineJumpTableEntry> &JT = MJTI.getJumpTables();

  if (JT.empty())
    return;

  StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";
  MCSection *JumpTableSizesSection = nullptr;
  StringRef sectionName = ".llvm_jump_table_sizes";

  bool isElf = TM.getTargetTriple().isOSBinFormatELF();
  bool isCoff = TM.getTargetTriple().isOSBinFormatCOFF();

  if (!isCoff && !isElf)
    return;

  if (isElf) {
    auto *LinkedToSym = static_cast<MCSymbolELF *>(CurrentFnSym);
    int Flags = F.hasComdat() ? static_cast<int>(ELF::SHF_GROUP) : 0;

    JumpTableSizesSection = OutContext.getELFSection(
        sectionName, ELF::SHT_LLVM_JT_SIZES, Flags, 0, GroupName, F.hasComdat(),
        MCSection::NonUniqueID, LinkedToSym);
  } else if (isCoff) {
    if (F.hasComdat()) {
      JumpTableSizesSection = OutContext.getCOFFSection(
          sectionName,
          COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
              COFF::IMAGE_SCN_LNK_COMDAT | COFF::IMAGE_SCN_MEM_DISCARDABLE,
          F.getComdat()->getName(), COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE);
    } else {
      JumpTableSizesSection = OutContext.getCOFFSection(
          sectionName, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
                           COFF::IMAGE_SCN_MEM_READ |
                           COFF::IMAGE_SCN_MEM_DISCARDABLE);
    }
  }

  OutStreamer->switchSection(JumpTableSizesSection);

  for (unsigned JTI = 0, E = JT.size(); JTI != E; ++JTI) {
    const std::vector<MachineBasicBlock *> &JTBBs = JT[JTI].MBBs;
    OutStreamer->emitSymbolValue(GetJTISymbol(JTI), TM.getProgramPointerSize());
    OutStreamer->emitIntValue(JTBBs.size(), TM.getProgramPointerSize());
  }
}

/// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the
/// current stream.
void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
                                    const MachineBasicBlock *MBB,
                                    unsigned UID) const {
  assert(MBB && MBB->getNumber() >= 0 && "Invalid basic block");
  const MCExpr *Value = nullptr;
  switch (MJTI.getEntryKind()) {
  case MachineJumpTableInfo::EK_Inline:
    llvm_unreachable("Cannot emit EK_Inline jump table entry");
  case MachineJumpTableInfo::EK_GPRel32BlockAddress:
  case MachineJumpTableInfo::EK_GPRel64BlockAddress:
    llvm_unreachable("MIPS specific");
  case MachineJumpTableInfo::EK_Custom32:
    Value = MF->getSubtarget().getTargetLowering()->LowerCustomJumpTableEntry(
        &MJTI, MBB, UID, OutContext);
    break;
  case MachineJumpTableInfo::EK_BlockAddress:
    // EK_BlockAddress - Each entry is a plain address of block, e.g.:
    //     .word LBB123
    Value = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
    break;

  case MachineJumpTableInfo::EK_LabelDifference32:
  case MachineJumpTableInfo::EK_LabelDifference64: {
    // Each entry is the address of the block minus the address of the jump
    // table. This is used for PIC jump tables where gprel32 is not supported.
    // e.g.:
    //      .word LBB123 - LJTI1_2
    // If the .set directive avoids relocations, this is emitted as:
    //      .set L4_5_set_123, LBB123 - LJTI1_2
    //      .word L4_5_set_123
    if (MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
        MAI.doesSetDirectiveSuppressReloc()) {
      Value = MCSymbolRefExpr::create(GetJTSetSymbol(UID, MBB->getNumber()),
                                      OutContext);
      break;
    }
    Value = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
    const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
    const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF, UID, OutContext);
    Value = MCBinaryExpr::createSub(Value, Base, OutContext);
    break;
  }
  }

  assert(Value && "Unknown entry kind!");

  unsigned EntrySize = MJTI.getEntrySize(getDataLayout());
  OutStreamer->emitValue(Value, EntrySize);
}

/// EmitSpecialLLVMGlobal - Check to see if the specified global is a
/// special global used by LLVM.  If so, emit it and return true, otherwise
/// do nothing and return false.
bool AsmPrinter::emitSpecialLLVMGlobal(const GlobalVariable *GV) {
  if (GV->getName() == "llvm.used") {
    if (MAI.hasNoDeadStrip()) // No need to emit this at all.
      emitLLVMUsedList(cast<ConstantArray>(GV->getInitializer()));
    return true;
  }

  // Ignore debug and non-emitted data.  This handles llvm.compiler.used.
  if (GV->getSection() == "llvm.metadata" ||
      GV->hasAvailableExternallyLinkage())
    return true;

  if (GV->getName() == "llvm.arm64ec.symbolmap") {
    // For ARM64EC, print the table that maps between symbols and the
    // corresponding thunks to translate between x64 and AArch64 code.
    // This table is generated by AArch64Arm64ECCallLowering.
    OutStreamer->switchSection(
        OutContext.getCOFFSection(".hybmp$x", COFF::IMAGE_SCN_LNK_INFO));
    auto *Arr = cast<ConstantArray>(GV->getInitializer());
    for (auto &U : Arr->operands()) {
      auto *C = cast<Constant>(U);
      auto *Src = cast<GlobalValue>(C->getOperand(0)->stripPointerCasts());
      auto *Dst = cast<GlobalValue>(C->getOperand(1)->stripPointerCasts());
      int Kind = cast<ConstantInt>(C->getOperand(2))->getZExtValue();

      if (Src->hasDLLImportStorageClass()) {
        // For now, we assume dllimport functions aren't directly called.
        // (We might change this later to match MSVC.)
        OutStreamer->emitCOFFSymbolIndex(
            OutContext.getOrCreateSymbol("__imp_" + Src->getName()));
        OutStreamer->emitCOFFSymbolIndex(getSymbol(Dst));
        OutStreamer->emitInt32(Kind);
      } else {
        // FIXME: For non-dllimport functions, MSVC emits the same entry
        // twice, for reasons I don't understand.  I have to assume the linker
        // ignores the redundant entry; there aren't any reasonable semantics
        // to attach to it.
        OutStreamer->emitCOFFSymbolIndex(getSymbol(Src));
        OutStreamer->emitCOFFSymbolIndex(getSymbol(Dst));
        OutStreamer->emitInt32(Kind);
      }
    }
    return true;
  }

  if (!GV->hasAppendingLinkage()) return false;

  assert(GV->hasInitializer() && "Not a special LLVM global!");

  if (GV->getName() == "llvm.global_ctors") {
    emitXXStructorList(GV->getDataLayout(), GV->getInitializer(),
                       /* isCtor */ true);

    return true;
  }

  if (GV->getName() == "llvm.global_dtors") {
    emitXXStructorList(GV->getDataLayout(), GV->getInitializer(),
                       /* isCtor */ false);

    return true;
  }

  GV->getContext().emitError(
      "unknown special variable with appending linkage: " +
      GV->getNameOrAsOperand());
  return true;
}

/// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each
/// global in the specified llvm.used list.
void AsmPrinter::emitLLVMUsedList(const ConstantArray *InitList) {
  // Should be an array of 'i8*'.
  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    const GlobalValue *GV =
      dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
    if (GV)
      OutStreamer->emitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip);
  }
}

void AsmPrinter::preprocessXXStructorList(const DataLayout &DL,
                                          const Constant *List,
                                          SmallVector<Structor, 8> &Structors) {
  // Should be an array of '{ i32, void ()*, i8* }' structs.  The first value is
  // the init priority.
  if (!isa<ConstantArray>(List))
    return;

  // Gather the structors in a form that's convenient for sorting by priority.
  for (Value *O : cast<ConstantArray>(List)->operands()) {
    auto *CS = cast<ConstantStruct>(O);
    if (CS->getOperand(1)->isNullValue())
      break; // Found a null terminator, skip the rest.
    ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
    if (!Priority)
      continue; // Malformed.
    Structors.push_back(Structor());
    Structor &S = Structors.back();
    S.Priority = Priority->getLimitedValue(65535);
    S.Func = CS->getOperand(1);
    if (!CS->getOperand(2)->isNullValue()) {
      if (TM.getTargetTriple().isOSAIX()) {
        CS->getContext().emitError(
            "associated data of XXStructor list is not yet supported on AIX");
      }

      S.ComdatKey =
          dyn_cast<GlobalValue>(CS->getOperand(2)->stripPointerCasts());
    }
  }

  // Emit the function pointers in the target-specific order
  llvm::stable_sort(Structors, [](const Structor &L, const Structor &R) {
    return L.Priority < R.Priority;
  });
}

/// EmitXXStructorList - Emit the ctor or dtor list taking into account the init
/// priority.
void AsmPrinter::emitXXStructorList(const DataLayout &DL, const Constant *List,
                                    bool IsCtor) {
  SmallVector<Structor, 8> Structors;
  preprocessXXStructorList(DL, List, Structors);
  if (Structors.empty())
    return;

  // Emit the structors in reverse order if we are using the .ctor/.dtor
  // initialization scheme.
  if (!TM.Options.UseInitArray)
    std::reverse(Structors.begin(), Structors.end());

  const Align Align = DL.getPointerPrefAlignment(DL.getProgramAddressSpace());
  for (Structor &S : Structors) {
    const TargetLoweringObjectFile &Obj = getObjFileLowering();
    const MCSymbol *KeySym = nullptr;
    if (GlobalValue *GV = S.ComdatKey) {
      if (GV->isDeclarationForLinker())
        // If the associated variable is not defined in this module
        // (it might be available_externally, or have been an
        // available_externally definition that was dropped by the
        // EliminateAvailableExternally pass), some other TU
        // will provide its dynamic initializer.
        continue;

      KeySym = getSymbol(GV);
    }

    MCSection *OutputSection =
        (IsCtor ? Obj.getStaticCtorSection(S.Priority, KeySym)
                : Obj.getStaticDtorSection(S.Priority, KeySym));
    OutStreamer->switchSection(OutputSection);
    if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection())
      emitAlignment(Align);
    emitXXStructor(DL, S.Func);
  }
}

void AsmPrinter::emitModuleIdents(Module &M) {
  if (!MAI.hasIdentDirective())
    return;

  if (const NamedMDNode *NMD = M.getNamedMetadata("llvm.ident")) {
    for (const MDNode *N : NMD->operands()) {
      assert(N->getNumOperands() == 1 &&
             "llvm.ident metadata entry can have only one operand");
      const MDString *S = cast<MDString>(N->getOperand(0));
      OutStreamer->emitIdent(S->getString());
    }
  }
}

void AsmPrinter::emitModuleCommandLines(Module &M) {
  MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines();
  if (!CommandLine)
    return;

  const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");
  if (!NMD || !NMD->getNumOperands())
    return;

  OutStreamer->pushSection();
  OutStreamer->switchSection(CommandLine);
  OutStreamer->emitZeros(1);
  for (const MDNode *N : NMD->operands()) {
    assert(N->getNumOperands() == 1 &&
           "llvm.commandline metadata entry can have only one operand");
    const MDString *S = cast<MDString>(N->getOperand(0));
    OutStreamer->emitBytes(S->getString());
    OutStreamer->emitZeros(1);
  }
  OutStreamer->popSection();
}

//===--------------------------------------------------------------------===//
// Emission and print routines
//

/// Emit a byte directive and value.
///
void AsmPrinter::emitInt8(int Value) const { OutStreamer->emitInt8(Value); }

/// Emit a short directive and value.
void AsmPrinter::emitInt16(int Value) const { OutStreamer->emitInt16(Value); }

/// Emit a long directive and value.
void AsmPrinter::emitInt32(int Value) const { OutStreamer->emitInt32(Value); }

/// EmitSLEB128 - emit the specified signed leb128 value.
void AsmPrinter::emitSLEB128(int64_t Value, const char *Desc) const {
  if (isVerbose() && Desc)
    OutStreamer->AddComment(Desc);

  OutStreamer->emitSLEB128IntValue(Value);
}

void AsmPrinter::emitULEB128(uint64_t Value, const char *Desc,
                             unsigned PadTo) const {
  if (isVerbose() && Desc)
    OutStreamer->AddComment(Desc);

  OutStreamer->emitULEB128IntValue(Value, PadTo);
}

/// Emit a long long directive and value.
void AsmPrinter::emitInt64(uint64_t Value) const {
  OutStreamer->emitInt64(Value);
}

/// Emit something like ".long Hi-Lo" where the size in bytes of the directive
/// is specified by Size and Hi/Lo specify the labels. This implicitly uses
/// .set if it avoids relocations.
void AsmPrinter::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
                                     unsigned Size) const {
  OutStreamer->emitAbsoluteSymbolDiff(Hi, Lo, Size);
}

/// Emit something like ".uleb128 Hi-Lo".
void AsmPrinter::emitLabelDifferenceAsULEB128(const MCSymbol *Hi,
                                              const MCSymbol *Lo) const {
  OutStreamer->emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
}

/// EmitLabelPlusOffset - Emit something like ".long Label+Offset"
/// where the size in bytes of the directive is specified by Size and Label
/// specifies the label.  This implicitly uses .set if it is available.
void AsmPrinter::emitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
                                     unsigned Size,
                                     bool IsSectionRelative) const {
  if (MAI.needsDwarfSectionOffsetDirective() && IsSectionRelative) {
    OutStreamer->emitCOFFSecRel32(Label, Offset);
    if (Size > 4)
      OutStreamer->emitZeros(Size - 4);
    return;
  }

  // Emit Label+Offset (or just Label if Offset is zero)
  const MCExpr *Expr = MCSymbolRefExpr::create(Label, OutContext);
  if (Offset)
    Expr = MCBinaryExpr::createAdd(
        Expr, MCConstantExpr::create(Offset, OutContext), OutContext);

  OutStreamer->emitValue(Expr, Size);
}

//===----------------------------------------------------------------------===//

// EmitAlignment - Emit an alignment directive to the specified power of
// two boundary.  If a global value is specified, and if that global has
// an explicit alignment requested, it will override the alignment request
// if required for correctness.
Align AsmPrinter::emitAlignment(Align Alignment, const GlobalObject *GV,
                                unsigned MaxBytesToEmit) const {
  if (GV)
    Alignment = getGVAlignment(GV, GV->getDataLayout(), Alignment);

  if (Alignment == Align(1))
    return Alignment; // 1-byte aligned: no need to emit alignment.

  if (getCurrentSection()->isText()) {
    const MCSubtargetInfo *STI = nullptr;
    if (this->MF)
      STI = &getSubtargetInfo();
    else
      STI = &TM.getMCSubtargetInfo();
    OutStreamer->emitCodeAlignment(Alignment, *STI, MaxBytesToEmit);
  } else
    OutStreamer->emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);
  return Alignment;
}

//===----------------------------------------------------------------------===//
// Constant emission.
//===----------------------------------------------------------------------===//

const MCExpr *AsmPrinter::lowerConstant(const Constant *CV,
                                        const Constant *BaseCV,
                                        uint64_t Offset) {
  MCContext &Ctx = OutContext;

  if (CV->isNullValue() || isa<UndefValue>(CV))
    return MCConstantExpr::create(0, Ctx);

  if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
    return MCConstantExpr::create(CI->getZExtValue(), Ctx);

  if (const ConstantByte *CB = dyn_cast<ConstantByte>(CV))
    return MCConstantExpr::create(CB->getZExtValue(), Ctx);

  if (const ConstantPtrAuth *CPA = dyn_cast<ConstantPtrAuth>(CV))
    return lowerConstantPtrAuth(*CPA);

  if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
    return MCSymbolRefExpr::create(getSymbol(GV), Ctx);

  if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV))
    return lowerBlockAddressConstant(*BA);

  if (const auto *Equiv = dyn_cast<DSOLocalEquivalent>(CV))
    return getObjFileLowering().lowerDSOLocalEquivalent(
        getSymbol(Equiv->getGlobalValue()), nullptr, 0, std::nullopt, TM);

  if (const NoCFIValue *NC = dyn_cast<NoCFIValue>(CV))
    return MCSymbolRefExpr::create(getSymbol(NC->getGlobalValue()), Ctx);

  const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
  if (!CE) {
    llvm_unreachable("Unknown constant value to lower!");
  }

  // The constant expression opcodes are limited to those that are necessary
  // to represent relocations on supported targets. Expressions involving only
  // constant addresses are constant folded instead.
  switch (CE->getOpcode()) {
  default:
    break; // Error
  case Instruction::AddrSpaceCast: {
    const Constant *Op = CE->getOperand(0);
    unsigned DstAS = CE->getType()->getPointerAddressSpace();
    unsigned SrcAS = Op->getType()->getPointerAddressSpace();
    if (TM.isNoopAddrSpaceCast(SrcAS, DstAS))
      return lowerConstant(Op);

    break; // Error
  }
  case Instruction::GetElementPtr: {
    // Generate a symbolic expression for the byte address
    APInt OffsetAI(getDataLayout().getPointerTypeSizeInBits(CE->getType()), 0);
    cast<GEPOperator>(CE)->accumulateConstantOffset(getDataLayout(), OffsetAI);

    const MCExpr *Base = lowerConstant(CE->getOperand(0));
    if (!OffsetAI)
      return Base;

    int64_t Offset = OffsetAI.getSExtValue();
    return MCBinaryExpr::createAdd(Base, MCConstantExpr::create(Offset, Ctx),
                                   Ctx);
  }

  case Instruction::Trunc:
    // We emit the value and depend on the assembler to truncate the generated
    // expression properly.  This is important for differences between
    // blockaddress labels.  Since the two labels are in the same function, it
    // is reasonable to treat their delta as a 32-bit value.
    [[fallthrough]];
  case Instruction::BitCast:
    return lowerConstant(CE->getOperand(0), BaseCV, Offset);

  case Instruction::IntToPtr: {
    const DataLayout &DL = getDataLayout();

    // Handle casts to pointers by changing them into casts to the appropriate
    // integer type.  This promotes constant folding and simplifies this code.
    Constant *Op = CE->getOperand(0);
    Op = ConstantFoldIntegerCast(Op, DL.getIntPtrType(CV->getType()),
                                 /*IsSigned*/ false, DL);
    if (Op)
      return lowerConstant(Op);

    break; // Error
  }

  case Instruction::PtrToAddr:
  case Instruction::PtrToInt: {
    const DataLayout &DL = getDataLayout();

    // Support only foldable casts to/from pointers that can be eliminated by
    // changing the pointer to the appropriately sized integer type.
    Constant *Op = CE->getOperand(0);
    Type *Ty = CE->getType();

    const MCExpr *OpExpr = lowerConstant(Op);

    // We can emit the pointer value into this slot if the slot is an
    // integer slot equal to the size of the pointer.
    //
    // If the pointer is larger than the resultant integer, then
    // as with Trunc just depend on the assembler to truncate it.
    if (DL.getTypeAllocSize(Ty).getFixedValue() <=
        DL.getTypeAllocSize(Op->getType()).getFixedValue())
      return OpExpr;

    break; // Error
  }

  case Instruction::Sub: {
    GlobalValue *LHSGV, *RHSGV;
    APInt LHSOffset, RHSOffset;
    DSOLocalEquivalent *DSOEquiv;
    if (IsConstantOffsetFromGlobal(CE->getOperand(0), LHSGV, LHSOffset,
                                   getDataLayout(), &DSOEquiv) &&
        IsConstantOffsetFromGlobal(CE->getOperand(1), RHSGV, RHSOffset,
                                   getDataLayout())) {
      auto *LHSSym = getSymbol(LHSGV);
      auto *RHSSym = getSymbol(RHSGV);
      int64_t Addend = (LHSOffset - RHSOffset).getSExtValue();
      std::optional<int64_t> PCRelativeOffset;
      if (getObjFileLowering().hasPLTPCRelative() && RHSGV == BaseCV)
        PCRelativeOffset = Offset;

      // Try the generic symbol difference first.
      const MCExpr *Res = getObjFileLowering().lowerRelativeReference(
          LHSGV, RHSGV, Addend, PCRelativeOffset, TM);

      // (ELF-specific) If the generic symbol difference does not apply, and
      // LHS is a dso_local_equivalent of a function, reference the PLT entry
      // instead. Note: A default visibility symbol is by default preemptible
      // during linking, and should not be referenced with PC-relative
      // relocations. Therefore, use a PLT relocation even if the function is
      // dso_local.
      if (DSOEquiv && TM.getTargetTriple().isOSBinFormatELF())
        Res = getObjFileLowering().lowerDSOLocalEquivalent(
            LHSSym, RHSSym, Addend, PCRelativeOffset, TM);

      // Otherwise, return LHS-RHS+Addend.
      if (!Res) {
        Res =
            MCBinaryExpr::createSub(MCSymbolRefExpr::create(LHSSym, Ctx),
                                    MCSymbolRefExpr::create(RHSSym, Ctx), Ctx);
        if (Addend != 0)
          Res = MCBinaryExpr::createAdd(
              Res, MCConstantExpr::create(Addend, Ctx), Ctx);
      }
      return Res;
    }

    const MCExpr *LHS = lowerConstant(CE->getOperand(0));
    const MCExpr *RHS = lowerConstant(CE->getOperand(1));
    return MCBinaryExpr::createSub(LHS, RHS, Ctx);
    break;
  }

  case Instruction::Add: {
    const MCExpr *LHS = lowerConstant(CE->getOperand(0));
    const MCExpr *RHS = lowerConstant(CE->getOperand(1));
    return MCBinaryExpr::createAdd(LHS, RHS, Ctx);
  }
  }

  // If the code isn't optimized, there may be outstanding folding
  // opportunities. Attempt to fold the expression using DataLayout as a
  // last resort before giving up.
  Constant *C = ConstantFoldConstant(CE, getDataLayout());
  if (C != CE)
    return lowerConstant(C);

  // Otherwise report the problem to the user.
  std::string S;
  raw_string_ostream OS(S);
  OS << "unsupported expression in static initializer: ";
  CE->printAsOperand(OS, /*PrintType=*/false,
                     !MF ? nullptr : MF->getFunction().getParent());
  CE->getContext().emitError(S);
  return MCConstantExpr::create(0, Ctx);
}

static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *C,
                                   AsmPrinter &AP,
                                   const Constant *BaseCV = nullptr,
                                   uint64_t Offset = 0,
                                   AsmPrinter::AliasMapTy *AliasList = nullptr);

static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP);
static void emitGlobalConstantFP(APFloat APF, Type *ET, AsmPrinter &AP);

/// isRepeatedByteSequence - Determine whether the given value is
/// composed of a repeated sequence of identical bytes and return the
/// byte value.  If it is not a repeated sequence, return -1.
static int isRepeatedByteSequence(const ConstantDataSequential *V) {
  StringRef Data = V->getRawDataValues();
  assert(!Data.empty() && "Empty aggregates should be CAZ node");
  char C = Data[0];
  for (unsigned i = 1, e = Data.size(); i != e; ++i)
    if (Data[i] != C) return -1;
  return static_cast<uint8_t>(C); // Ensure 255 is not returned as -1.
}

/// isRepeatedByteSequence - Determine whether the given value is
/// composed of a repeated sequence of identical bytes and return the
/// byte value.  If it is not a repeated sequence, return -1.
static int isRepeatedByteSequence(const Value *V, const DataLayout &DL) {
  if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
    uint64_t Size = DL.getTypeAllocSizeInBits(V->getType());
    assert(Size % 8 == 0);

    // Extend the element to take zero padding into account.
    APInt Value = CI->getValue().zext(Size);
    if (!Value.isSplat(8))
      return -1;

    return Value.zextOrTrunc(8).getZExtValue();
  }
  if (const ConstantArray *CA = dyn_cast<ConstantArray>(V)) {
    // Make sure all array elements are sequences of the same repeated
    // byte.
    assert(CA->getNumOperands() != 0 && "Should be a CAZ");
    Constant *Op0 = CA->getOperand(0);
    int Byte = isRepeatedByteSequence(Op0, DL);
    if (Byte == -1)
      return -1;

    // All array elements must be equal.
    for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i)
      if (CA->getOperand(i) != Op0)
        return -1;
    return Byte;
  }

  if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(V))
    return isRepeatedByteSequence(CDS);

  return -1;
}

static void emitGlobalAliasInline(AsmPrinter &AP, uint64_t Offset,
                                  AsmPrinter::AliasMapTy *AliasList) {
  if (AliasList) {
    auto AliasIt = AliasList->find(Offset);
    if (AliasIt != AliasList->end()) {
      for (const GlobalAlias *GA : AliasIt->second)
        AP.OutStreamer->emitLabel(AP.getSymbol(GA));
      AliasList->erase(Offset);
    }
  }
}

static void emitGlobalConstantDataSequential(
    const DataLayout &DL, const ConstantDataSequential *CDS, AsmPrinter &AP,
    AsmPrinter::AliasMapTy *AliasList) {
  // See if we can aggregate this into a .fill, if so, emit it as such.
  int Value = isRepeatedByteSequence(CDS, DL);
  if (Value != -1) {
    uint64_t Bytes = DL.getTypeAllocSize(CDS->getType());
    // Don't emit a 1-byte object as a .fill.
    if (Bytes > 1)
      return AP.OutStreamer->emitFill(Bytes, Value);
  }

  // If this can be emitted with .ascii/.asciz, emit it as such.
  if (CDS->isString())
    return AP.OutStreamer->emitBytes(CDS->getAsString());

  // Otherwise, emit the values in successive locations.
  uint64_t ElementByteSize = CDS->getElementByteSize();
  if (isa<IntegerType>(CDS->getElementType()) ||
      isa<ByteType>(CDS->getElementType())) {
    for (uint64_t I = 0, E = CDS->getNumElements(); I != E; ++I) {
      emitGlobalAliasInline(AP, ElementByteSize * I, AliasList);
      if (AP.isVerbose())
        AP.OutStreamer->getCommentOS()
            << format("0x%" PRIx64 "\n", CDS->getElementAsInteger(I));
      AP.OutStreamer->emitIntValue(CDS->getElementAsInteger(I),
                                   ElementByteSize);
    }
  } else {
    Type *ET = CDS->getElementType();
    for (uint64_t I = 0, E = CDS->getNumElements(); I != E; ++I) {
      emitGlobalAliasInline(AP, ElementByteSize * I, AliasList);
      emitGlobalConstantFP(CDS->getElementAsAPFloat(I), ET, AP);
    }
  }

  unsigned Size = DL.getTypeAllocSize(CDS->getType());
  unsigned EmittedSize =
      DL.getTypeAllocSize(CDS->getElementType()) * CDS->getNumElements();
  assert(EmittedSize <= Size && "Size cannot be less than EmittedSize!");
  if (unsigned Padding = Size - EmittedSize)
    AP.OutStreamer->emitZeros(Padding);
}

static void emitGlobalConstantArray(const DataLayout &DL,
                                    const ConstantArray *CA, AsmPrinter &AP,
                                    const Constant *BaseCV, uint64_t Offset,
                                    AsmPrinter::AliasMapTy *AliasList) {
  // See if we can aggregate some values.  Make sure it can be
  // represented as a series of bytes of the constant value.
  int Value = isRepeatedByteSequence(CA, DL);

  if (Value != -1) {
    uint64_t Bytes = DL.getTypeAllocSize(CA->getType());
    AP.OutStreamer->emitFill(Bytes, Value);
  } else {
    for (unsigned I = 0, E = CA->getNumOperands(); I != E; ++I) {
      emitGlobalConstantImpl(DL, CA->getOperand(I), AP, BaseCV, Offset,
                             AliasList);
      Offset += DL.getTypeAllocSize(CA->getOperand(I)->getType());
    }
  }
}

static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP);

static void emitGlobalConstantVector(const DataLayout &DL, const Constant *CV,
                                     AsmPrinter &AP,
                                     AsmPrinter::AliasMapTy *AliasList) {
  uint64_t AllocSize = DL.getTypeAllocSize(CV->getType());

  if (CV->isNullValue())
    return AP.OutStreamer->emitZeros(AllocSize);

  auto *VTy = cast<FixedVectorType>(CV->getType());
  Type *ElementType = VTy->getElementType();
  uint64_t ElementSizeInBits = DL.getTypeSizeInBits(ElementType);
  uint64_t ElementAllocSizeInBits = DL.getTypeAllocSizeInBits(ElementType);
  uint64_t EmittedSize;
  if (ElementSizeInBits != ElementAllocSizeInBits) {
    // If the allocation size of an element is different from the size in bits,
    // printing each element separately will insert incorrect padding.
    //
    // The general algorithm here is complicated; instead of writing it out
    // here, just use the existing code in ConstantFolding.
    Type *IntT =
        IntegerType::get(CV->getContext(), DL.getTypeSizeInBits(CV->getType()));
    ConstantInt *CI = dyn_cast_or_null<ConstantInt>(ConstantFoldConstant(
        ConstantExpr::getBitCast(const_cast<Constant *>(CV), IntT), DL));
    if (!CI) {
      report_fatal_error(
          "Cannot lower vector global with unusual element type");
    }
    emitGlobalAliasInline(AP, 0, AliasList);
    emitGlobalConstantLargeInt(CI, AP);
    EmittedSize = DL.getTypeStoreSize(CV->getType());
  } else {
    for (unsigned I = 0, E = VTy->getNumElements(); I != E; ++I) {
      emitGlobalAliasInline(AP, AllocSize * I, AliasList);
      emitGlobalConstantImpl(DL, CV->getAggregateElement(I), AP);
    }
    EmittedSize = DL.getTypeAllocSize(ElementType) * VTy->getNumElements();
  }

  if (unsigned Padding = AllocSize - EmittedSize)
    AP.OutStreamer->emitZeros(Padding);
}

static void emitGlobalConstantStruct(const DataLayout &DL,
                                     const ConstantStruct *CS, AsmPrinter &AP,
                                     const Constant *BaseCV, uint64_t Offset,
                                     AsmPrinter::AliasMapTy *AliasList) {
  // Print the fields in successive locations. Pad to align if needed!
  uint64_t Size = DL.getTypeAllocSize(CS->getType());
  const StructLayout *Layout = DL.getStructLayout(CS->getType());
  uint64_t SizeSoFar = 0;
  for (unsigned I = 0, E = CS->getNumOperands(); I != E; ++I) {
    const Constant *Field = CS->getOperand(I);

    // Print the actual field value.
    emitGlobalConstantImpl(DL, Field, AP, BaseCV, Offset + SizeSoFar,
                           AliasList);

    // Check if padding is needed and insert one or more 0s.
    uint64_t FieldSize = DL.getTypeAllocSize(Field->getType());
    uint64_t PadSize = ((I == E - 1 ? Size : Layout->getElementOffset(I + 1)) -
                        Layout->getElementOffset(I)) -
                       FieldSize;
    SizeSoFar += FieldSize + PadSize;

    // Insert padding - this may include padding to increase the size of the
    // current field up to the ABI size (if the struct is not packed) as well
    // as padding to ensure that the next field starts at the right offset.
    AP.OutStreamer->emitZeros(PadSize);
  }
  assert(SizeSoFar == Layout->getSizeInBytes() &&
         "Layout of constant struct may be incorrect!");
}

static void emitGlobalConstantFP(APFloat APF, Type *ET, AsmPrinter &AP) {
  assert(ET && "Unknown float type");
  APInt API = APF.bitcastToAPInt();

  // First print a comment with what we think the original floating-point value
  // should have been.
  if (AP.isVerbose()) {
    SmallString<8> StrVal;
    APF.toString(StrVal);
    ET->print(AP.OutStreamer->getCommentOS());
    AP.OutStreamer->getCommentOS() << ' ' << StrVal << '\n';
  }

  // Now iterate through the APInt chunks, emitting them in endian-correct
  // order, possibly with a smaller chunk at beginning/end (e.g. for x87 80-bit
  // floats).
  unsigned NumBytes = API.getBitWidth() / 8;
  unsigned TrailingBytes = NumBytes % sizeof(uint64_t);
  const uint64_t *p = API.getRawData();

  // PPC's long double has odd notions of endianness compared to how LLVM
  // handles it: p[0] goes first for *big* endian on PPC.
  if (AP.getDataLayout().isBigEndian() && !ET->isPPC_FP128Ty()) {
    int Chunk = API.getNumWords() - 1;

    if (TrailingBytes)
      AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk--], TrailingBytes);

    for (; Chunk >= 0; --Chunk)
      AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], sizeof(uint64_t));
  } else {
    unsigned Chunk;
    for (Chunk = 0; Chunk < NumBytes / sizeof(uint64_t); ++Chunk)
      AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], sizeof(uint64_t));

    if (TrailingBytes)
      AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], TrailingBytes);
  }

  // Emit the tail padding for the long double.
  const DataLayout &DL = AP.getDataLayout();
  AP.OutStreamer->emitZeros(DL.getTypeAllocSize(ET) - DL.getTypeStoreSize(ET));
}

static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
  emitGlobalConstantFP(CFP->getValueAPF(), CFP->getType(), AP);
}

static void emitGlobalConstantLargeAPInt(const APInt &Val,
                                         uint64_t TypeStoreSize,
                                         AsmPrinter &AP) {
  const DataLayout &DL = AP.getDataLayout();
  unsigned BitWidth = Val.getBitWidth();

  // Copy the value as we may massage the layout for constants whose bit width
  // is not a multiple of 64-bits.
  APInt Realigned(Val);
  uint64_t ExtraBits = 0;
  unsigned ExtraBitsSize = BitWidth & 63;

  if (ExtraBitsSize) {
    // The bit width of the data is not a multiple of 64-bits.
    // The extra bits are expected to be at the end of the chunk of the memory.
    // Little endian:
    // * Nothing to be done, just record the extra bits to emit.
    // Big endian:
    // * Record the extra bits to emit.
    // * Realign the raw data to emit the chunks of 64-bits.
    if (DL.isBigEndian()) {
      // Basically the structure of the raw data is a chunk of 64-bits cells:
      //    0        1         BitWidth / 64
      // [chunk1][chunk2] ... [chunkN].
      // The most significant chunk is chunkN and it should be emitted first.
      // However, due to the alignment issue chunkN contains useless bits.
      // Realign the chunks so that they contain only useful information:
      // ExtraBits     0       1       (BitWidth / 64) - 1
      //       chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN]
      ExtraBitsSize = alignTo(ExtraBitsSize, 8);
      ExtraBits =
          Realigned.getRawData()[0] & (((uint64_t)-1) >> (64 - ExtraBitsSize));
      if (BitWidth >= 64)
        Realigned.lshrInPlace(ExtraBitsSize);
    } else
      ExtraBits = Realigned.getRawData()[BitWidth / 64];
  }

  // We don't expect assemblers to support data directives
  // for more than 64 bits, so we emit the data in at most 64-bit
  // quantities at a time.
  const uint64_t *RawData = Realigned.getRawData();
  for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
    uint64_t ChunkVal = DL.isBigEndian() ? RawData[e - i - 1] : RawData[i];
    AP.OutStreamer->emitIntValue(ChunkVal, 8);
  }

  if (ExtraBitsSize) {
    // Emit the extra bits after the 64-bits chunks.

    // Emit a directive that fills the expected size.
    uint64_t Size = TypeStoreSize - (BitWidth / 64) * 8;
    assert(Size && Size * 8 >= ExtraBitsSize &&
           (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) ==
               ExtraBits &&
           "Directive too small for extra bits.");
    AP.OutStreamer->emitIntValue(ExtraBits, Size);
  }
}

static void emitGlobalConstantLargeByte(const ConstantByte *CB,
                                        AsmPrinter &AP) {
  emitGlobalConstantLargeAPInt(
      CB->getValue(), AP.getDataLayout().getTypeStoreSize(CB->getType()), AP);
}

static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
  emitGlobalConstantLargeAPInt(
      CI->getValue(), AP.getDataLayout().getTypeStoreSize(CI->getType()), AP);
}

/// Transform a not absolute MCExpr containing a reference to a GOT
/// equivalent global, by a target specific GOT pc relative access to the
/// final symbol.
static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
                                         const Constant *BaseCst,
                                         uint64_t Offset) {
  // The global @foo below illustrates a global that uses a got equivalent.
  //
  //  @bar = global i32 42
  //  @gotequiv = private unnamed_addr constant i32* @bar
  //  @foo = i32 trunc (i64 sub (i64 ptrtoint (i32** @gotequiv to i64),
  //                             i64 ptrtoint (i32* @foo to i64))
  //                        to i32)
  //
  // The cstexpr in @foo is converted into the MCExpr `ME`, where we actually
  // check whether @foo is suitable to use a GOTPCREL. `ME` is usually in the
  // form:
  //
  //  foo = cstexpr, where
  //    cstexpr := <gotequiv> - "." + <cst>
  //    cstexpr := <gotequiv> - (<foo> - <offset from @foo base>) + <cst>
  //
  // After canonicalization by evaluateAsRelocatable `ME` turns into:
  //
  //  cstexpr := <gotequiv> - <foo> + gotpcrelcst, where
  //    gotpcrelcst := <offset from @foo base> + <cst>
  MCValue MV;
  if (!(*ME)->evaluateAsRelocatable(MV, nullptr) || MV.isAbsolute())
    return;
  const MCSymbol *GOTEquivSym = MV.getAddSym();
  if (!GOTEquivSym)
    return;

  // Check that GOT equivalent symbol is cached.
  if (!AP.GlobalGOTEquivs.count(GOTEquivSym))
    return;

  const GlobalValue *BaseGV = dyn_cast_or_null<GlobalValue>(BaseCst);
  if (!BaseGV)
    return;

  // Check for a valid base symbol
  const MCSymbol *BaseSym = AP.getSymbol(BaseGV);
  const MCSymbol *SymB = MV.getSubSym();

  if (!SymB || BaseSym != SymB)
    return;

  // Make sure to match:
  //
  //    gotpcrelcst := <offset from @foo base> + <cst>
  //
  int64_t GOTPCRelCst = Offset + MV.getConstant();
  if (!AP.getObjFileLowering().supportGOTPCRelWithOffset() && GOTPCRelCst != 0)
    return;

  // Emit the GOT PC relative to replace the got equivalent global, i.e.:
  //
  //  bar:
  //    .long 42
  //  gotequiv:
  //    .quad bar
  //  foo:
  //    .long gotequiv - "." + <cst>
  //
  // is replaced by the target specific equivalent to:
  //
  //  bar:
  //    .long 42
  //  foo:
  //    .long bar@GOTPCREL+<gotpcrelcst>
  AsmPrinter::GOTEquivUsePair Result = AP.GlobalGOTEquivs[GOTEquivSym];
  const GlobalVariable *GV = Result.first;
  int NumUses = (int)Result.second;
  const GlobalValue *FinalGV = dyn_cast<GlobalValue>(GV->getOperand(0));
  const MCSymbol *FinalSym = AP.getSymbol(FinalGV);
  *ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(
      FinalGV, FinalSym, MV, Offset, AP.MMI, *AP.OutStreamer);

  // Update GOT equivalent usage information
  --NumUses;
  if (NumUses >= 0)
    AP.GlobalGOTEquivs[GOTEquivSym] = std::make_pair(GV, NumUses);
}

static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
                                   AsmPrinter &AP, const Constant *BaseCV,
                                   uint64_t Offset,
                                   AsmPrinter::AliasMapTy *AliasList) {
  assert((!AliasList || AP.TM.getTargetTriple().isOSBinFormatXCOFF()) &&
         "AliasList only expected for XCOFF");
  emitGlobalAliasInline(AP, Offset, AliasList);
  uint64_t Size = DL.getTypeAllocSize(CV->getType());

  // Globals with sub-elements such as combinations of arrays and structs
  // are handled recursively by emitGlobalConstantImpl. Keep track of the
  // constant symbol base and the current position with BaseCV and Offset.
  if (!BaseCV && CV->hasOneUse())
    BaseCV = dyn_cast<Constant>(CV->user_back());

  if (isa<ConstantAggregateZero>(CV)) {
    StructType *structType;
    if (AliasList && (structType = llvm::dyn_cast<StructType>(CV->getType()))) {
      unsigned numElements = {structType->getNumElements()};
      if (numElements != 0) {
        // Handle cases of aliases to direct struct elements
        const StructLayout *Layout = DL.getStructLayout(structType);
        uint64_t SizeSoFar = 0;
        for (unsigned int i = 0; i < numElements - 1; ++i) {
          uint64_t GapToNext = Layout->getElementOffset(i + 1) - SizeSoFar;
          AP.OutStreamer->emitZeros(GapToNext);
          SizeSoFar += GapToNext;
          emitGlobalAliasInline(AP, Offset + SizeSoFar, AliasList);
        }
        AP.OutStreamer->emitZeros(Size - SizeSoFar);
        return;
      }
    }
    return AP.OutStreamer->emitZeros(Size);
  }

  if (isa<UndefValue>(CV))
    return AP.OutStreamer->emitZeros(Size);

  if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
    if (isa<VectorType>(CV->getType()))
      return emitGlobalConstantVector(DL, CV, AP, AliasList);

    const uint64_t StoreSize = DL.getTypeStoreSize(CV->getType());
    if (StoreSize <= 8) {
      if (AP.isVerbose())
        AP.OutStreamer->getCommentOS()
            << format("0x%" PRIx64 "\n", CI->getZExtValue());
      AP.OutStreamer->emitIntValue(CI->getZExtValue(), StoreSize);
    } else {
      emitGlobalConstantLargeInt(CI, AP);
    }

    // Emit tail padding if needed
    if (Size != StoreSize)
      AP.OutStreamer->emitZeros(Size - StoreSize);

    return;
  }

  if (const ConstantByte *CB = dyn_cast<ConstantByte>(CV)) {
    if (isa<VectorType>(CV->getType()))
      return emitGlobalConstantVector(DL, CV, AP, AliasList);

    const uint64_t StoreSize = DL.getTypeStoreSize(CV->getType());
    if (StoreSize <= 8) {
      if (AP.isVerbose())
        AP.OutStreamer->getCommentOS()
            << format("0x%" PRIx64 "\n", CB->getZExtValue());
      AP.OutStreamer->emitIntValue(CB->getZExtValue(), StoreSize);
    } else {
      emitGlobalConstantLargeByte(CB, AP);
    }

    // Emit tail padding if needed
    if (Size != StoreSize)
      AP.OutStreamer->emitZeros(Size - StoreSize);

    return;
  }

  if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    if (isa<VectorType>(CV->getType()))
      return emitGlobalConstantVector(DL, CV, AP, AliasList);
    else
      return emitGlobalConstantFP(CFP, AP);
  }

  if (isa<ConstantPointerNull>(CV)) {
    AP.OutStreamer->emitIntValue(0, Size);
    return;
  }

  if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(CV))
    return emitGlobalConstantDataSequential(DL, CDS, AP, AliasList);

  if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
    return emitGlobalConstantArray(DL, CVA, AP, BaseCV, Offset, AliasList);

  if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
    return emitGlobalConstantStruct(DL, CVS, AP, BaseCV, Offset, AliasList);

  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    // Look through bitcasts, which might not be able to be MCExpr'ized (e.g. of
    // vectors).
    if (CE->getOpcode() == Instruction::BitCast)
      return emitGlobalConstantImpl(DL, CE->getOperand(0), AP);

    if (Size > 8) {
      // If the constant expression's size is greater than 64-bits, then we have
      // to emit the value in chunks. Try to constant fold the value and emit it
      // that way.
      Constant *New = ConstantFoldConstant(CE, DL);
      if (New != CE)
        return emitGlobalConstantImpl(DL, New, AP);
    }
  }

  if (isa<ConstantVector>(CV))
    return emitGlobalConstantVector(DL, CV, AP, AliasList);

  // Otherwise, it must be a ConstantExpr.  Lower it to an MCExpr, then emit it
  // thread the streamer with EmitValue.
  const MCExpr *ME = AP.lowerConstant(CV, BaseCV, Offset);

  // Since lowerConstant already folded and got rid of all IR pointer and
  // integer casts, detect GOT equivalent accesses by looking into the MCExpr
  // directly.
  if (AP.getObjFileLowering().supportIndirectSymViaGOTPCRel())
    handleIndirectSymViaGOTPCRel(AP, &ME, BaseCV, Offset);

  AP.OutStreamer->emitValue(ME, Size);
}

/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
void AsmPrinter::emitGlobalConstant(const DataLayout &DL, const Constant *CV,
                                    AliasMapTy *AliasList) {
  uint64_t Size = DL.getTypeAllocSize(CV->getType());
  if (Size)
    emitGlobalConstantImpl(DL, CV, *this, nullptr, 0, AliasList);
  else if (MAI.hasSubsectionsViaSymbols()) {
    // If the global has zero size, emit a single byte so that two labels don't
    // look like they are at the same location.
    OutStreamer->emitIntValue(0, 1);
  }
  if (!AliasList)
    return;
  // TODO: These remaining aliases are not emitted in the correct location. Need
  // to handle the case where the alias offset doesn't refer to any sub-element.
  for (auto &AliasPair : *AliasList) {
    for (const GlobalAlias *GA : AliasPair.second)
      OutStreamer->emitLabel(getSymbol(GA));
  }
}

void AsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
  // Target doesn't support this yet!
  llvm_unreachable("Target does not support EmitMachineConstantPoolValue");
}

void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const {
  if (Offset > 0)
    OS << '+' << Offset;
  else if (Offset < 0)
    OS << Offset;
}

void AsmPrinter::emitNops(unsigned N) {
  MCInst Nop = MF->getSubtarget().getInstrInfo()->getNop();
  for (; N; --N)
    EmitToStreamer(*OutStreamer, Nop);
}

//===----------------------------------------------------------------------===//
// Symbol Lowering Routines.
//===----------------------------------------------------------------------===//

MCSymbol *AsmPrinter::createTempSymbol(const Twine &Name) const {
  return OutContext.createTempSymbol(Name, true);
}

MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const {
  return const_cast<AsmPrinter *>(this)->getAddrLabelSymbol(
      BA->getBasicBlock());
}

MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const {
  return const_cast<AsmPrinter *>(this)->getAddrLabelSymbol(BB);
}

const MCExpr *AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) {
  return MCSymbolRefExpr::create(GetBlockAddressSymbol(&BA), OutContext);
}

/// GetCPISymbol - Return the symbol for the specified constant pool entry.
MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const {
  if (getSubtargetInfo().getTargetTriple().isWindowsMSVCEnvironment() ||
      getSubtargetInfo().getTargetTriple().isUEFI()) {
    const MachineConstantPoolEntry &CPE =
        MF->getConstantPool()->getConstants()[CPID];
    if (!CPE.isMachineConstantPoolEntry()) {
      const DataLayout &DL = MF->getDataLayout();
      SectionKind Kind = CPE.getSectionKind(&DL);
      const Constant *C = CPE.Val.ConstVal;
      Align Alignment = CPE.Alignment;
      auto *S = getObjFileLowering().getSectionForConstant(
          DL, Kind, C, Alignment, &MF->getFunction());
      if (S && TM.getTargetTriple().isOSBinFormatCOFF()) {
        if (MCSymbol *Sym =
                static_cast<const MCSectionCOFF *>(S)->getCOMDATSymbol()) {
          if (Sym->isUndefined())
            OutStreamer->emitSymbolAttribute(Sym, MCSA_Global);
          return Sym;
        }
      }
    }
  }

  const DataLayout &DL = getDataLayout();
  return OutContext.getOrCreateSymbol(Twine(DL.getInternalSymbolPrefix()) +
                                      "CPI" + Twine(getFunctionNumber()) + "_" +
                                      Twine(CPID));
}

/// GetJTISymbol - Return the symbol for the specified jump table entry.
MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
  return MF->getJTISymbol(JTID, OutContext, isLinkerPrivate);
}

/// GetJTSetSymbol - Return the symbol for the specified jump table .set
/// FIXME: privatize to AsmPrinter.
MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
  const DataLayout &DL = getDataLayout();
  return OutContext.getOrCreateSymbol(Twine(DL.getInternalSymbolPrefix()) +
                                      Twine(getFunctionNumber()) + "_" +
                                      Twine(UID) + "_set_" + Twine(MBBID));
}

MCSymbol *AsmPrinter::getSymbolWithGlobalValueBase(const GlobalValue *GV,
                                                   StringRef Suffix) const {
  return getObjFileLowering().getSymbolWithGlobalValueBase(GV, Suffix, TM);
}

/// Return the MCSymbol for the specified ExternalSymbol.
MCSymbol *AsmPrinter::GetExternalSymbolSymbol(const Twine &Sym) const {
  SmallString<60> NameStr;
  Mangler::getNameWithPrefix(NameStr, Sym, getDataLayout());
  return OutContext.getOrCreateSymbol(NameStr);
}

/// PrintParentLoopComment - Print comments about parent loops of this one.
static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop,
                                   unsigned FunctionNumber) {
  if (!Loop) return;
  PrintParentLoopComment(OS, Loop->getParentLoop(), FunctionNumber);
  OS.indent(Loop->getLoopDepth()*2)
    << "Parent Loop BB" << FunctionNumber << "_"
    << Loop->getHeader()->getNumber()
    << " Depth=" << Loop->getLoopDepth() << '\n';
}

/// PrintChildLoopComment - Print comments about child loops within
/// the loop for this basic block, with nesting.
static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop,
                                  unsigned FunctionNumber) {
  // Add child loop information
  for (const MachineLoop *CL : *Loop) {
    OS.indent(CL->getLoopDepth()*2)
      << "Child Loop BB" << FunctionNumber << "_"
      << CL->getHeader()->getNumber() << " Depth " << CL->getLoopDepth()
      << '\n';
    PrintChildLoopComment(OS, CL, FunctionNumber);
  }
}

/// emitBasicBlockLoopComments - Pretty-print comments for basic blocks.
static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB,
                                       const MachineLoopInfo *LI,
                                       const AsmPrinter &AP) {
  // Add loop depth information
  const MachineLoop *Loop = LI->getLoopFor(&MBB);
  if (!Loop) return;

  MachineBasicBlock *Header = Loop->getHeader();
  assert(Header && "No header for loop");

  // If this block is not a loop header, just print out what is the loop header
  // and return.
  if (Header != &MBB) {
    AP.OutStreamer->AddComment("  in Loop: Header=BB" +
                               Twine(AP.getFunctionNumber())+"_" +
                               Twine(Loop->getHeader()->getNumber())+
                               " Depth="+Twine(Loop->getLoopDepth()));
    return;
  }

  // Otherwise, it is a loop header.  Print out information about child and
  // parent loops.
  raw_ostream &OS = AP.OutStreamer->getCommentOS();

  PrintParentLoopComment(OS, Loop->getParentLoop(), AP.getFunctionNumber());

  OS << "=>";
  OS.indent(Loop->getLoopDepth()*2-2);

  OS << "This ";
  if (Loop->isInnermost())
    OS << "Inner ";
  OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n';

  PrintChildLoopComment(OS, Loop, AP.getFunctionNumber());
}

/// emitBasicBlockStart - This method prints the label for the specified
/// MachineBasicBlock, an alignment (if present) and a comment describing
/// it if appropriate.
void AsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
  // End the previous funclet and start a new one.
  if (MBB.isEHFuncletEntry()) {
    for (auto &Handler : Handlers) {
      Handler->endFunclet();
      Handler->beginFunclet(MBB);
    }
    for (auto &Handler : EHHandlers) {
      Handler->endFunclet();
      Handler->beginFunclet(MBB);
    }
  }

  // Switch to a new section if this basic block must begin a section. The
  // entry block is always placed in the function section and is handled
  // separately.
  if (MBB.isBeginSection() && !MBB.isEntryBlock()) {
    OutStreamer->switchSection(
        getObjFileLowering().getSectionForMachineBasicBlock(MF->getFunction(),
                                                            MBB, TM));
    CurrentSectionBeginSym = MBB.getSymbol();
  }

  for (auto &Handler : Handlers)
    Handler->beginCodeAlignment(MBB);

  // Emit an alignment directive for this block, if needed.
  const Align Alignment = MBB.getAlignment();
  if (Alignment != Align(1))
    emitAlignment(Alignment, nullptr, MBB.getMaxBytesForAlignment());

  // If the block has its address taken, emit any labels that were used to
  // reference the block.  It is possible that there is more than one label
  // here, because multiple LLVM BB's may have been RAUW'd to this block after
  // the references were generated.
  if (MBB.isIRBlockAddressTaken()) {
    if (isVerbose())
      OutStreamer->AddComment("Block address taken");

    BasicBlock *BB = MBB.getAddressTakenIRBlock();
    assert(BB && BB->hasAddressTaken() && "Missing BB");
    for (MCSymbol *Sym : getAddrLabelSymbolToEmit(BB))
      OutStreamer->emitLabel(Sym);
  } else if (isVerbose() && MBB.isMachineBlockAddressTaken()) {
    OutStreamer->AddComment("Block address taken");
  } else if (isVerbose() && MBB.isInlineAsmBrIndirectTarget()) {
    OutStreamer->AddComment("Inline asm indirect target");
  }

  // Print some verbose block comments.
  if (isVerbose()) {
    if (const BasicBlock *BB = MBB.getBasicBlock()) {
      if (BB->hasName()) {
        BB->printAsOperand(OutStreamer->getCommentOS(),
                           /*PrintType=*/false, BB->getModule());
        OutStreamer->getCommentOS() << '\n';
      }
    }

    assert(MLI != nullptr && "MachineLoopInfo should has been computed");
    emitBasicBlockLoopComments(MBB, MLI, *this);
  }

  // Print the main label for the block.
  if (shouldEmitLabelForBasicBlock(MBB)) {
    if (isVerbose() && MBB.hasLabelMustBeEmitted())
      OutStreamer->AddComment("Label of block must be emitted");
    OutStreamer->emitLabel(MBB.getSymbol());
  } else {
    if (isVerbose()) {
      // NOTE: Want this comment at start of line, don't emit with AddComment.
      OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":",
                                  false);
    }
  }

  if (MBB.isEHContTarget() &&
      MAI.getExceptionHandlingType() == ExceptionHandling::WinEH) {
    OutStreamer->emitLabel(MBB.getEHContSymbol());
  }

  // With BB sections, each basic block must handle CFI information on its own
  // if it begins a section (Entry block call is handled separately, next to
  // beginFunction).
  if (MBB.isBeginSection() && !MBB.isEntryBlock()) {
    for (auto &Handler : Handlers)
      Handler->beginBasicBlockSection(MBB);
    for (auto &Handler : EHHandlers)
      Handler->beginBasicBlockSection(MBB);
  }
}

void AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) {
  // Check if CFI information needs to be updated for this MBB with basic block
  // sections.
  if (MBB.isEndSection()) {
    for (auto &Handler : Handlers)
      Handler->endBasicBlockSection(MBB);
    for (auto &Handler : EHHandlers)
      Handler->endBasicBlockSection(MBB);
  }
}

void AsmPrinter::emitVisibility(MCSymbol *Sym, unsigned Visibility,
                                bool IsDefinition) const {
  MCSymbolAttr Attr = MCSA_Invalid;

  switch (Visibility) {
  default: break;
  case GlobalValue::HiddenVisibility:
    if (IsDefinition)
      Attr = MAI.getHiddenVisibilityAttr();
    else
      Attr = MAI.getHiddenDeclarationVisibilityAttr();
    break;
  case GlobalValue::ProtectedVisibility:
    Attr = MAI.getProtectedVisibilityAttr();
    break;
  }

  if (Attr != MCSA_Invalid)
    OutStreamer->emitSymbolAttribute(Sym, Attr);
}

bool AsmPrinter::shouldEmitLabelForBasicBlock(
    const MachineBasicBlock &MBB) const {
  // With `-fbasic-block-sections=`, a label is needed for every non-entry block
  // in the labels mode (option `=labels`) and every section beginning in the
  // sections mode (`=all` and `=list=`).
  if ((MF->getTarget().Options.BBAddrMap || MBB.isBeginSection()) &&
      !MBB.isEntryBlock())
    return true;
  // A label is needed for any block with at least one predecessor (when that
  // predecessor is not the fallthrough predecessor, or if it is an EH funclet
  // entry, or if a label is forced).
  return !MBB.pred_empty() &&
         (!isBlockOnlyReachableByFallthrough(&MBB) || MBB.isEHFuncletEntry() ||
          MBB.hasLabelMustBeEmitted());
}

/// isBlockOnlyReachableByFallthough - Return true if the basic block has
/// exactly one predecessor and the control transfer mechanism between
/// the predecessor and this block is a fall-through.
bool AsmPrinter::
isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
  // If this is a landing pad, it isn't a fall through.  If it has no preds,
  // then nothing falls through to it.
  if (MBB->isEHPad() || MBB->pred_empty())
    return false;

  // If there isn't exactly one predecessor, it can't be a fall through.
  if (MBB->pred_size() > 1)
    return false;

  // The predecessor has to be immediately before this block.
  MachineBasicBlock *Pred = *MBB->pred_begin();
  if (!Pred->isLayoutSuccessor(MBB))
    return false;

  // If the block is completely empty, then it definitely does fall through.
  if (Pred->empty())
    return true;

  // Check the terminators in the previous blocks
  for (const auto &MI : Pred->terminators()) {
    // If it is not a simple branch, we are in a table somewhere.
    if (!MI.isBranch() || MI.isIndirectBranch())
      return false;

    // If we are the operands of one of the branches, this is not a fall
    // through. Note that targets with delay slots will usually bundle
    // terminators with the delay slot instruction.
    for (ConstMIBundleOperands OP(MI); OP.isValid(); ++OP) {
      if (OP->isJTI())
        return false;
      if (OP->isMBB() && OP->getMBB() == MBB)
        return false;
    }
  }

  return true;
}

GCMetadataPrinter *AsmPrinter::getOrCreateGCPrinter(GCStrategy &S) {
  if (!S.usesMetadata())
    return nullptr;

  auto [GCPI, Inserted] = GCMetadataPrinters.try_emplace(&S);
  if (!Inserted)
    return GCPI->second.get();

  auto Name = S.getName();

  for (const GCMetadataPrinterRegistry::entry &GCMetaPrinter :
       GCMetadataPrinterRegistry::entries())
    if (Name == GCMetaPrinter.getName()) {
      std::unique_ptr<GCMetadataPrinter> GMP = GCMetaPrinter.instantiate();
      GMP->S = &S;
      GCPI->second = std::move(GMP);
      return GCPI->second.get();
    }

  report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name));
}

void AsmPrinter::addAsmPrinterHandler(
    std::unique_ptr<AsmPrinterHandler> Handler) {
  Handlers.insert(Handlers.begin(), std::move(Handler));
  NumUserHandlers++;
}

/// Pin vtables to this file.
AsmPrinterHandler::~AsmPrinterHandler() = default;

void AsmPrinterHandler::markFunctionEnd() {}

// In the binary's "xray_instr_map" section, an array of these function entries
// describes each instrumentation point.  When XRay patches your code, the index
// into this table will be given to your handler as a patch point identifier.
void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out) const {
  auto Kind8 = static_cast<uint8_t>(Kind);
  Out->emitBinaryData(StringRef(reinterpret_cast<const char *>(&Kind8), 1));
  Out->emitBinaryData(
      StringRef(reinterpret_cast<const char *>(&AlwaysInstrument), 1));
  Out->emitBinaryData(StringRef(reinterpret_cast<const char *>(&Version), 1));
  auto Padding = (4 * Bytes) - ((2 * Bytes) + 3);
  assert(Padding >= 0 && "Instrumentation map entry > 4 * Word Size");
  Out->emitZeros(Padding);
}

void AsmPrinter::emitXRayTable() {
  if (Sleds.empty())
    return;

  auto PrevSection = OutStreamer->getCurrentSectionOnly();
  const Function &F = MF->getFunction();
  MCSection *InstMap = nullptr;
  MCSection *FnSledIndex = nullptr;
  const Triple &TT = TM.getTargetTriple();
  // Use PC-relative addresses on all targets.
  if (TT.isOSBinFormatELF()) {
    auto LinkedToSym = static_cast<const MCSymbolELF *>(CurrentFnSym);
    auto Flags = ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER;
    StringRef GroupName;
    if (F.hasComdat()) {
      Flags |= ELF::SHF_GROUP;
      GroupName = F.getComdat()->getName();
    }
    InstMap = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
                                       Flags, 0, GroupName, F.hasComdat(),
                                       MCSection::NonUniqueID, LinkedToSym);

    if (TM.Options.XRayFunctionIndex)
      FnSledIndex = OutContext.getELFSection(
          "xray_fn_idx", ELF::SHT_PROGBITS, Flags, 0, GroupName, F.hasComdat(),
          MCSection::NonUniqueID, LinkedToSym);
  } else if (MF->getSubtarget().getTargetTriple().isOSBinFormatMachO()) {
    InstMap = OutContext.getMachOSection("__DATA", "xray_instr_map",
                                         MachO::S_ATTR_LIVE_SUPPORT,
                                         SectionKind::getReadOnlyWithRel());
    if (TM.Options.XRayFunctionIndex)
      FnSledIndex = OutContext.getMachOSection("__DATA", "xray_fn_idx",
                                               MachO::S_ATTR_LIVE_SUPPORT,
                                               SectionKind::getReadOnly());
  } else {
    llvm_unreachable("Unsupported target");
  }

  auto WordSizeBytes = MAI.getCodePointerSize();

  // Now we switch to the instrumentation map section. Because this is done
  // per-function, we are able to create an index entry that will represent the
  // range of sleds associated with a function.
  auto &Ctx = OutContext;
  MCSymbol *SledsStart =
      OutContext.createLinkerPrivateSymbol("xray_sleds_start");
  OutStreamer->switchSection(InstMap);
  OutStreamer->emitLabel(SledsStart);
  for (const auto &Sled : Sleds) {
    MCSymbol *Dot = Ctx.createTempSymbol();
    OutStreamer->emitLabel(Dot);
    OutStreamer->emitValueImpl(
        MCBinaryExpr::createSub(MCSymbolRefExpr::create(Sled.Sled, Ctx),
                                MCSymbolRefExpr::create(Dot, Ctx), Ctx),
        WordSizeBytes);
    OutStreamer->emitValueImpl(
        MCBinaryExpr::createSub(
            MCSymbolRefExpr::create(CurrentFnBegin, Ctx),
            MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Dot, Ctx),
                                    MCConstantExpr::create(WordSizeBytes, Ctx),
                                    Ctx),
            Ctx),
        WordSizeBytes);
    Sled.emit(WordSizeBytes, OutStreamer.get());
  }
  MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_sleds_end", true);
  OutStreamer->emitLabel(SledsEnd);

  // We then emit a single entry in the index per function. We use the symbols
  // that bound the instrumentation map as the range for a specific function.
  // Each entry contains 2 words and needs to be word-aligned.
  if (FnSledIndex) {
    OutStreamer->switchSection(FnSledIndex);
    OutStreamer->emitValueToAlignment(Align(WordSizeBytes));
    // For Mach-O, use an "l" symbol as the atom of this subsection. The label
    // difference uses a SUBTRACTOR external relocation which references the
    // symbol.
    MCSymbol *Dot = Ctx.createLinkerPrivateSymbol("xray_fn_idx");
    OutStreamer->emitLabel(Dot);
    OutStreamer->emitValueImpl(
        MCBinaryExpr::createSub(MCSymbolRefExpr::create(SledsStart, Ctx),
                                MCSymbolRefExpr::create(Dot, Ctx), Ctx),
        WordSizeBytes);
    OutStreamer->emitValueImpl(MCConstantExpr::create(Sleds.size(), Ctx),
                               WordSizeBytes);
    OutStreamer->switchSection(PrevSection);
  }
  Sleds.clear();
}

void AsmPrinter::recordSled(MCSymbol *Sled, const MachineInstr &MI,
                            SledKind Kind, uint8_t Version) {
  const Function &F = MI.getMF()->getFunction();
  auto Attr = F.getFnAttribute("function-instrument");
  bool LogArgs = F.hasFnAttribute("xray-log-args");
  bool AlwaysInstrument =
    Attr.isStringAttribute() && Attr.getValueAsString() == "xray-always";
  if (Kind == SledKind::FUNCTION_ENTER && LogArgs)
    Kind = SledKind::LOG_ARGS_ENTER;
  Sleds.emplace_back(XRayFunctionEntry{Sled, CurrentFnSym, Kind,
                                       AlwaysInstrument, &F, Version});
}

void AsmPrinter::emitPatchableFunctionEntries() {
  const Function &F = MF->getFunction();
  unsigned PatchableFunctionPrefix =
      F.getFnAttributeAsParsedInteger("patchable-function-prefix");
  unsigned PatchableFunctionEntry =
      F.getFnAttributeAsParsedInteger("patchable-function-entry");
  if (!PatchableFunctionPrefix && !PatchableFunctionEntry)
    return;
  const unsigned PointerSize = getPointerSize();
  if (TM.getTargetTriple().isOSBinFormatELF()) {
    auto Flags = ELF::SHF_WRITE | ELF::SHF_ALLOC;
    const MCSymbolELF *LinkedToSym = nullptr;
    StringRef GroupName, SectionName;

    if (F.hasFnAttribute("patchable-function-entry-section"))
      SectionName = F.getFnAttribute("patchable-function-entry-section")
                        .getValueAsString();
    if (SectionName.empty())
      SectionName = "__patchable_function_entries";

    // GNU as < 2.35 did not support section flag 'o'. GNU ld < 2.36 did not
    // support mixed SHF_LINK_ORDER and non-SHF_LINK_ORDER sections.
    if (MAI.useIntegratedAssembler() || MAI.binutilsIsAtLeast(2, 36)) {
      Flags |= ELF::SHF_LINK_ORDER;
      if (F.hasComdat()) {
        Flags |= ELF::SHF_GROUP;
        GroupName = F.getComdat()->getName();
      }
      LinkedToSym = static_cast<const MCSymbolELF *>(CurrentFnSym);
    }
    OutStreamer->switchSection(OutContext.getELFSection(
        SectionName, ELF::SHT_PROGBITS, Flags, 0, GroupName, F.hasComdat(),
        MCSection::NonUniqueID, LinkedToSym));
    emitAlignment(Align(PointerSize));
    OutStreamer->emitSymbolValue(CurrentPatchableFunctionEntrySym, PointerSize);
  }
}

uint16_t AsmPrinter::getDwarfVersion() const {
  return OutStreamer->getContext().getDwarfVersion();
}

void AsmPrinter::setDwarfVersion(uint16_t Version) {
  OutStreamer->getContext().setDwarfVersion(Version);
}

bool AsmPrinter::isDwarf64() const {
  return OutStreamer->getContext().getDwarfFormat() == dwarf::DWARF64;
}

unsigned int AsmPrinter::getDwarfOffsetByteSize() const {
  return dwarf::getDwarfOffsetByteSize(
      OutStreamer->getContext().getDwarfFormat());
}

dwarf::FormParams AsmPrinter::getDwarfFormParams() const {
  return {getDwarfVersion(), uint8_t(MAI.getCodePointerSize()),
          OutStreamer->getContext().getDwarfFormat(),
          doesDwarfUseRelocationsAcrossSections()};
}

unsigned int AsmPrinter::getUnitLengthFieldByteSize() const {
  return dwarf::getUnitLengthFieldByteSize(
      OutStreamer->getContext().getDwarfFormat());
}

std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,
           codeview::JumpTableEntrySize>
AsmPrinter::getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr,
                                     const MCSymbol *BranchLabel) const {
  const auto TLI = MF->getSubtarget().getTargetLowering();
  const auto BaseExpr =
      TLI->getPICJumpTableRelocBaseExpr(MF, JTI, MMI->getContext());
  const auto Base = &cast<MCSymbolRefExpr>(BaseExpr)->getSymbol();

  // By default, for the architectures that support CodeView,
  // EK_LabelDifference32 is implemented as an Int32 from the base address.
  return std::make_tuple(Base, 0, BranchLabel,
                         codeview::JumpTableEntrySize::Int32);
}

void AsmPrinter::emitCOFFReplaceableFunctionData(Module &M) {
  const Triple &TT = TM.getTargetTriple();
  assert(TT.isOSBinFormatCOFF());

  bool IsTargetArm64EC = TT.isWindowsArm64EC();
  SmallVector<char> Buf;
  SmallVector<MCSymbol *> FuncOverrideDefaultSymbols;
  bool SwitchedToDirectiveSection = false;
  for (const Function &F : M.functions()) {
    if (F.hasFnAttribute("loader-replaceable")) {
      if (!SwitchedToDirectiveSection) {
        OutStreamer->switchSection(
            OutContext.getObjectFileInfo()->getDrectveSection());
        SwitchedToDirectiveSection = true;
      }

      StringRef Name = F.getName();

      // For hybrid-patchable targets, strip the prefix so that we can mark
      // the real function as replaceable.
      if (IsTargetArm64EC && Name.ends_with(HybridPatchableTargetSuffix)) {
        Name = Name.drop_back(HybridPatchableTargetSuffix.size());
      }

      MCSymbol *FuncOverrideSymbol =
          MMI->getContext().getOrCreateSymbol(Name + "_$fo$");
      OutStreamer->beginCOFFSymbolDef(FuncOverrideSymbol);
      OutStreamer->emitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_EXTERNAL);
      OutStreamer->emitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL);
      OutStreamer->endCOFFSymbolDef();

      MCSymbol *FuncOverrideDefaultSymbol =
          MMI->getContext().getOrCreateSymbol(Name + "_$fo_default$");
      OutStreamer->beginCOFFSymbolDef(FuncOverrideDefaultSymbol);
      OutStreamer->emitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_EXTERNAL);
      OutStreamer->emitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL);
      OutStreamer->endCOFFSymbolDef();
      FuncOverrideDefaultSymbols.push_back(FuncOverrideDefaultSymbol);

      OutStreamer->emitBytes((Twine(" /ALTERNATENAME:") +
                              FuncOverrideSymbol->getName() + "=" +
                              FuncOverrideDefaultSymbol->getName())
                                 .toStringRef(Buf));
      Buf.clear();
    }
  }

  if (SwitchedToDirectiveSection)
    OutStreamer->popSection();

  if (FuncOverrideDefaultSymbols.empty())
    return;

  // MSVC emits the symbols for the default variables pointing at the start of
  // the .data section, but doesn't actually allocate any space for them. LLVM
  // can't do this, so have all of the variables pointing at a single byte
  // instead.
  OutStreamer->switchSection(OutContext.getObjectFileInfo()->getDataSection());
  for (MCSymbol *Symbol : FuncOverrideDefaultSymbols) {
    OutStreamer->emitLabel(Symbol);
  }
  OutStreamer->emitZeros(1);
  OutStreamer->popSection();
}

void AsmPrinter::emitCOFFFeatureSymbol(Module &M) {
  const Triple &TT = TM.getTargetTriple();
  assert(TT.isOSBinFormatCOFF());

  // Emit an absolute @feat.00 symbol.
  MCSymbol *S = MMI->getContext().getOrCreateSymbol(StringRef("@feat.00"));
  OutStreamer->beginCOFFSymbolDef(S);
  OutStreamer->emitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC);
  OutStreamer->emitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_NULL);
  OutStreamer->endCOFFSymbolDef();
  int64_t Feat00Value = 0;

  if (TT.getArch() == Triple::x86) {
    // According to the PE-COFF spec, the LSB of this value marks the object
    // for "registered SEH".  This means that all SEH handler entry points
    // must be registered in .sxdata.  Use of any unregistered handlers will
    // cause the process to terminate immediately.  LLVM does not know how to
    // register any SEH handlers, so its object files should be safe.
    Feat00Value |= COFF::Feat00Flags::SafeSEH;
  }

  if (M.getControlFlowGuardMode() == ControlFlowGuardMode::Enabled) {
    // Object is CFG-aware. Only set if we actually inserted the checks.
    Feat00Value |= COFF::Feat00Flags::GuardCF;
  }

  if (M.getModuleFlag("ehcontguard")) {
    // Object also has EHCont.
    Feat00Value |= COFF::Feat00Flags::GuardEHCont;
  }

  if (M.getModuleFlag("ms-kernel")) {
    // Object is compiled with /kernel.
    Feat00Value |= COFF::Feat00Flags::Kernel;
  }

  OutStreamer->emitSymbolAttribute(S, MCSA_Global);
  OutStreamer->emitAssignment(
      S, MCConstantExpr::create(Feat00Value, MMI->getContext()));
}

namespace llvm {
namespace {
MachineFunctionAnalysisManager &getMFAM(Module &M, ModuleAnalysisManager &MAM,
                                        MachineFunction &MF) {
  FunctionAnalysisManager &FAM =
      MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
  MachineFunctionAnalysisManager &MFAM =
      FAM.getResult<MachineFunctionAnalysisManagerFunctionProxy>(
             MF.getFunction())
          .getManager();
  return MFAM;
}
} // anonymous namespace

void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM,
                           AsmPrinter &AsmPrinter) {
  MachineModuleInfo &MMI = MAM.getResult<MachineModuleAnalysis>(M).getMMI();
  AsmPrinter.GetMMI = [&MMI]() { return &MMI; };
  AsmPrinter.MMI = &MMI;
  AsmPrinter.GetORE = [&MAM, &M](MachineFunction &MF) {
    return &getMFAM(M, MAM, MF)
                .getResult<MachineOptimizationRemarkEmitterAnalysis>(MF);
  };
  AsmPrinter.GetMDT = [&MAM, &M](MachineFunction &MF) {
    return &getMFAM(M, MAM, MF).getResult<MachineDominatorTreeAnalysis>(MF);
  };
  AsmPrinter.GetMLI = [&MAM, &M](MachineFunction &MF) {
    return &getMFAM(M, MAM, MF).getResult<MachineLoopAnalysis>(MF);
  };
  // TODO(boomanaiden154): Get GC working with the new pass manager.
  AsmPrinter.BeginGCAssembly = [](Module &M) {};
  AsmPrinter.FinishGCAssembly = [](Module &M) {};
  AsmPrinter.EmitStackMaps = [](Module &M) {};
  AsmPrinter.AssertDebugEHFinalized = []() {};
}

void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM,
                                    MachineFunction &MF,
                                    AsmPrinter &AsmPrinter) {
  const ModuleAnalysisManagerMachineFunctionProxy::Result &MAMProxy =
      MFAM.getResult<ModuleAnalysisManagerMachineFunctionProxy>(MF);
  MachineModuleInfo &MMI =
      MAMProxy
          .getCachedResult<MachineModuleAnalysis>(*MF.getFunction().getParent())
          ->getMMI();
  AsmPrinter.GetMMI = [&MMI]() { return &MMI; };
  AsmPrinter.MMI = &MMI;
  AsmPrinter.GetORE = [&MFAM](MachineFunction &MF) {
    return &MFAM.getResult<MachineOptimizationRemarkEmitterAnalysis>(MF);
  };
  AsmPrinter.GetMDT = [&MFAM](MachineFunction &MF) {
    return &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
  };
  AsmPrinter.GetMLI = [&MFAM](MachineFunction &MF) {
    return &MFAM.getResult<MachineLoopAnalysis>(MF);
  };
  // TODO(boomanaiden154): Get GC working with the new pass manager.
  AsmPrinter.BeginGCAssembly = [](Module &M) {};
  AsmPrinter.FinishGCAssembly = [](Module &M) {};
  AsmPrinter.EmitStackMaps = [](Module &M) {};
  AsmPrinter.AssertDebugEHFinalized = []() {};
}

AnalysisKey AsmPrinterAnalysis::Key;

} // namespace llvm
