//===- 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/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 "llvm/TargetParser/Triple.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());
}

void AsmPrinter::emitInitialRawDwarfLocDirective(const MachineFunction &MF) {
  if (DD) {
    assert(OutStreamer->hasRawTextSupport() &&
           "Expected assembly output mode.");
    // This is NVPTX specific and it's unclear why.
    // PR51079: If we have code without debug information we need to give up.
    DISubprogram *MFSP = MF.getFunction().getSubprogram();
    if (!MFSP)
      return;
    (void)DD->emitInitialLocDirective(MF, /*CUID=*/0);
  }
}

/// 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.getModuleInlineAsm().empty()) {
    OutStreamer->AddComment("Start of file scope inline assembly");
    OutStreamer->addBlankLine();
    emitInlineAsm(
        M.getModuleInlineAsm() + "\n", *TM.getMCSubtargetInfo(),
        TM.Options.MCOptions, nullptr,
        InlineAsm::AsmDialect(TM.getMCAsmInfo()->getAssemblerDialect()));
    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) {
  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).
  const Align Alignment = getGVAlignment(GV, DL);

  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 = 0;
  unsigned PatchableFunctionEntry = 0;
  (void)F.getFnAttribute("patchable-function-prefix")
      .getValueAsString()
      .getAsInteger(10, PatchableFunctionPrefix);
  (void)F.getFnAttribute("patchable-function-entry")
      .getValueAsString()
      .getAsInteger(10, PatchableFunctionEntry);
  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.
  MapVector<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->getCount() : 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 generalized numeric type identifier of a Function's type from
/// type metadata. Returns null if metadata cannot be found.
static ConstantInt *extractNumericCGTypeId(const Function &F) {
  SmallVector<MDNode *, 2> Types;
  F.getMetadata(LLVMContext::MD_type, Types);
  for (const auto &Type : Types) {
    if (Type->hasGeneralizedMDString()) {
      MDString *MDGeneralizedTypeId = cast<MDString>(Type->getOperand(1));
      uint64_t TypeIdVal = llvm::MD5Hash(MDGeneralizedTypeId->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()) {
    // Get MachineDominatorTree or compute it on the fly if it's unavailable
    MDT = GetMDT(*MF);
    if (!MDT) {
      OwnedMDT = std::make_unique<MachineDominatorTree>();
      OwnedMDT->recalculate(*MF);
      MDT = OwnedMDT.get();
    }

    // Get MachineLoopInfo or compute it on the fly if it's unavailable
    MLI = GetMLI(*MF);
    if (!MLI) {
      OwnedMLI = std::make_unique<MachineLoopInfo>();
      OwnedMLI->analyze(*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);
          if (MI.isBundled()) {
            // Bundled instructions are emitted together.
            auto It = MI.getIterator(), End = MBB.instr_end();
            for (++It; It != End && It->isInsideBundle(); ++It)
              ExpectedSize += TII->getInstSizeInBytes(*It);
          }

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

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

      Offset = NewOffset + CPE.getSizeInBytes(getDataLayout());

      OutStreamer->emitLabel(Sym);
      if (CPE.isMachineConstantPoolEntry())
        emitMachineConstantPoolValue(CPE.Val.MachineCPVal);
      else
        emitGlobalConstant(getDataLayout(), CPE.Val.ConstVal);
    }
  }
}

// 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);
    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 (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) {
  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, DL.getTypeAllocSize(CV->getType()) * I, AliasList);
      emitGlobalConstantImpl(DL, CV->getAggregateElement(I), AP);
    }
    EmittedSize = DL.getTypeAllocSize(ElementType) * VTy->getNumElements();
  }

  unsigned Size = DL.getTypeAllocSize(CV->getType());
  if (unsigned Padding = Size - 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 = 0, PatchableFunctionEntry = 0;
  (void)F.getFnAttribute("patchable-function-prefix")
      .getValueAsString()
      .getAsInteger(10, PatchableFunctionPrefix);
  (void)F.getFnAttribute("patchable-function-entry")
      .getValueAsString()
      .getAsInteger(10, PatchableFunctionEntry);
  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
