//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/MC/MCStreamer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeView.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCPseudoProbe.h"
#include "llvm/MC/MCRegister.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCWin64EH.h"
#include "llvm/MC/MCWinEH.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <optional>
#include <utility>

using namespace llvm;

MCTargetStreamer::MCTargetStreamer(MCStreamer &S) : Streamer(S) {
  S.setTargetStreamer(this);
}

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

void MCTargetStreamer::emitLabel(MCSymbol *Symbol) {}

void MCTargetStreamer::finish() {}

void MCTargetStreamer::emitConstantPools() {}

void MCTargetStreamer::changeSection(const MCSection *CurSection,
                                     MCSection *Section,
                                     const MCExpr *Subsection,
                                     raw_ostream &OS) {
  Section->printSwitchToSection(*Streamer.getContext().getAsmInfo(),
                                Streamer.getContext().getTargetTriple(), OS,
                                Subsection);
}

void MCTargetStreamer::emitDwarfFileDirective(StringRef Directive) {
  Streamer.emitRawText(Directive);
}

void MCTargetStreamer::emitValue(const MCExpr *Value) {
  SmallString<128> Str;
  raw_svector_ostream OS(Str);

  Value->print(OS, Streamer.getContext().getAsmInfo());
  Streamer.emitRawText(OS.str());
}

void MCTargetStreamer::emitRawBytes(StringRef Data) {
  const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
  const char *Directive = MAI->getData8bitsDirective();
  for (const unsigned char C : Data.bytes()) {
    SmallString<128> Str;
    raw_svector_ostream OS(Str);

    OS << Directive << (unsigned)C;
    Streamer.emitRawText(OS.str());
  }
}

void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}

MCStreamer::MCStreamer(MCContext &Ctx)
    : Context(Ctx), CurrentWinFrameInfo(nullptr),
      CurrentProcWinFrameInfoStartIndex(0), UseAssemblerInfoForParsing(false) {
  SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
}

MCStreamer::~MCStreamer() = default;

void MCStreamer::reset() {
  DwarfFrameInfos.clear();
  CurrentWinFrameInfo = nullptr;
  WinFrameInfos.clear();
  SymbolOrdering.clear();
  SectionStack.clear();
  SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
}

raw_ostream &MCStreamer::getCommentOS() {
  // By default, discard comments.
  return nulls();
}

unsigned MCStreamer::getNumFrameInfos() { return DwarfFrameInfos.size(); }
ArrayRef<MCDwarfFrameInfo> MCStreamer::getDwarfFrameInfos() const {
  return DwarfFrameInfos;
}

void MCStreamer::emitRawComment(const Twine &T, bool TabPrefix) {}

void MCStreamer::addExplicitComment(const Twine &T) {}
void MCStreamer::emitExplicitComments() {}

void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) {
  for (auto &FI : DwarfFrameInfos)
    FI.CompactUnwindEncoding =
        (MAB ? MAB->generateCompactUnwindEncoding(&FI, &Context) : 0);
}

/// EmitIntValue - Special case of EmitValue that avoids the client having to
/// pass in a MCExpr for constant integers.
void MCStreamer::emitIntValue(uint64_t Value, unsigned Size) {
  assert(1 <= Size && Size <= 8 && "Invalid size");
  assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&
         "Invalid size");
  const bool IsLittleEndian = Context.getAsmInfo()->isLittleEndian();
  uint64_t Swapped = support::endian::byte_swap(
      Value, IsLittleEndian ? llvm::endianness::little : llvm::endianness::big);
  unsigned Index = IsLittleEndian ? 0 : 8 - Size;
  emitBytes(StringRef(reinterpret_cast<char *>(&Swapped) + Index, Size));
}
void MCStreamer::emitIntValue(APInt Value) {
  if (Value.getNumWords() == 1) {
    emitIntValue(Value.getLimitedValue(), Value.getBitWidth() / 8);
    return;
  }

  const bool IsLittleEndianTarget = Context.getAsmInfo()->isLittleEndian();
  const bool ShouldSwap = sys::IsLittleEndianHost != IsLittleEndianTarget;
  const APInt Swapped = ShouldSwap ? Value.byteSwap() : Value;
  const unsigned Size = Value.getBitWidth() / 8;
  SmallString<10> Tmp;
  Tmp.resize(Size);
  StoreIntToMemory(Swapped, reinterpret_cast<uint8_t *>(Tmp.data()), Size);
  emitBytes(Tmp.str());
}

/// EmitULEB128IntValue - Special case of EmitULEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.
unsigned MCStreamer::emitULEB128IntValue(uint64_t Value, unsigned PadTo) {
  SmallString<128> Tmp;
  raw_svector_ostream OSE(Tmp);
  encodeULEB128(Value, OSE, PadTo);
  emitBytes(OSE.str());
  return Tmp.size();
}

/// EmitSLEB128IntValue - Special case of EmitSLEB128Value that avoids the
/// client having to pass in a MCExpr for constant integers.
unsigned MCStreamer::emitSLEB128IntValue(int64_t Value) {
  SmallString<128> Tmp;
  raw_svector_ostream OSE(Tmp);
  encodeSLEB128(Value, OSE);
  emitBytes(OSE.str());
  return Tmp.size();
}

void MCStreamer::emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc) {
  emitValueImpl(Value, Size, Loc);
}

void MCStreamer::emitSymbolValue(const MCSymbol *Sym, unsigned Size,
                                 bool IsSectionRelative) {
  assert((!IsSectionRelative || Size == 4) &&
         "SectionRelative value requires 4-bytes");

  if (!IsSectionRelative)
    emitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size);
  else
    emitCOFFSecRel32(Sym, /*Offset=*/0);
}

void MCStreamer::emitDTPRel64Value(const MCExpr *Value) {
  report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::emitDTPRel32Value(const MCExpr *Value) {
  report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::emitTPRel64Value(const MCExpr *Value) {
  report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::emitTPRel32Value(const MCExpr *Value) {
  report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::emitGPRel64Value(const MCExpr *Value) {
  report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::emitGPRel32Value(const MCExpr *Value) {
  report_fatal_error("unsupported directive in streamer");
}

/// Emit NumBytes bytes worth of the value specified by FillValue.
/// This implements directives such as '.space'.
void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
  if (NumBytes)
    emitFill(*MCConstantExpr::create(NumBytes, getContext()), FillValue);
}

void llvm::MCStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLen,
                                llvm::SMLoc, const MCSubtargetInfo& STI) {}

/// The implementation in this class just redirects to emitFill.
void MCStreamer::emitZeros(uint64_t NumBytes) { emitFill(NumBytes, 0); }

Expected<unsigned> MCStreamer::tryEmitDwarfFileDirective(
    unsigned FileNo, StringRef Directory, StringRef Filename,
    std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
    unsigned CUID) {
  return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum,
                                   Source, CUID);
}

void MCStreamer::emitDwarfFile0Directive(StringRef Directory,
                                         StringRef Filename,
                                         std::optional<MD5::MD5Result> Checksum,
                                         std::optional<StringRef> Source,
                                         unsigned CUID) {
  getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
                                      Source);
}

void MCStreamer::emitCFIBKeyFrame() {
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->IsBKeyFrame = true;
}

void MCStreamer::emitCFIMTETaggedFrame() {
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->IsMTETaggedFrame = true;
}

void MCStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
                                       unsigned Column, unsigned Flags,
                                       unsigned Isa, unsigned Discriminator,
                                       StringRef FileName) {
  getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
                                  Discriminator);
}

MCSymbol *MCStreamer::getDwarfLineTableSymbol(unsigned CUID) {
  MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
  if (!Table.getLabel()) {
    StringRef Prefix = Context.getAsmInfo()->getPrivateGlobalPrefix();
    Table.setLabel(
        Context.getOrCreateSymbol(Prefix + "line_table_start" + Twine(CUID)));
  }
  return Table.getLabel();
}

bool MCStreamer::hasUnfinishedDwarfFrameInfo() {
  return !FrameInfoStack.empty();
}

MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() {
  if (!hasUnfinishedDwarfFrameInfo()) {
    getContext().reportError(getStartTokLoc(),
                             "this directive must appear between "
                             ".cfi_startproc and .cfi_endproc directives");
    return nullptr;
  }
  return &DwarfFrameInfos[FrameInfoStack.back().first];
}

bool MCStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename,
                                     ArrayRef<uint8_t> Checksum,
                                     unsigned ChecksumKind) {
  return getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
                                             ChecksumKind);
}

bool MCStreamer::emitCVFuncIdDirective(unsigned FunctionId) {
  return getContext().getCVContext().recordFunctionId(FunctionId);
}

bool MCStreamer::emitCVInlineSiteIdDirective(unsigned FunctionId,
                                             unsigned IAFunc, unsigned IAFile,
                                             unsigned IALine, unsigned IACol,
                                             SMLoc Loc) {
  if (getContext().getCVContext().getCVFunctionInfo(IAFunc) == nullptr) {
    getContext().reportError(Loc, "parent function id not introduced by "
                                  ".cv_func_id or .cv_inline_site_id");
    return true;
  }

  return getContext().getCVContext().recordInlinedCallSiteId(
      FunctionId, IAFunc, IAFile, IALine, IACol);
}

void MCStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
                                    unsigned Line, unsigned Column,
                                    bool PrologueEnd, bool IsStmt,
                                    StringRef FileName, SMLoc Loc) {}

bool MCStreamer::checkCVLocSection(unsigned FuncId, unsigned FileNo,
                                   SMLoc Loc) {
  CodeViewContext &CVC = getContext().getCVContext();
  MCCVFunctionInfo *FI = CVC.getCVFunctionInfo(FuncId);
  if (!FI) {
    getContext().reportError(
        Loc, "function id not introduced by .cv_func_id or .cv_inline_site_id");
    return false;
  }

  // Track the section
  if (FI->Section == nullptr)
    FI->Section = getCurrentSectionOnly();
  else if (FI->Section != getCurrentSectionOnly()) {
    getContext().reportError(
        Loc,
        "all .cv_loc directives for a function must be in the same section");
    return false;
  }
  return true;
}

void MCStreamer::emitCVLinetableDirective(unsigned FunctionId,
                                          const MCSymbol *Begin,
                                          const MCSymbol *End) {}

void MCStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
                                                unsigned SourceFileId,
                                                unsigned SourceLineNum,
                                                const MCSymbol *FnStartSym,
                                                const MCSymbol *FnEndSym) {}

/// Only call this on endian-specific types like ulittle16_t and little32_t, or
/// structs composed of them.
template <typename T>
static void copyBytesForDefRange(SmallString<20> &BytePrefix,
                                 codeview::SymbolKind SymKind,
                                 const T &DefRangeHeader) {
  BytePrefix.resize(2 + sizeof(T));
  codeview::ulittle16_t SymKindLE = codeview::ulittle16_t(SymKind);
  memcpy(&BytePrefix[0], &SymKindLE, 2);
  memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T));
}

void MCStreamer::emitCVDefRangeDirective(
    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
    StringRef FixedSizePortion) {}

void MCStreamer::emitCVDefRangeDirective(
    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
    codeview::DefRangeRegisterRelHeader DRHdr) {
  SmallString<20> BytePrefix;
  copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER_REL, DRHdr);
  emitCVDefRangeDirective(Ranges, BytePrefix);
}

void MCStreamer::emitCVDefRangeDirective(
    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
    codeview::DefRangeSubfieldRegisterHeader DRHdr) {
  SmallString<20> BytePrefix;
  copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_SUBFIELD_REGISTER,
                       DRHdr);
  emitCVDefRangeDirective(Ranges, BytePrefix);
}

void MCStreamer::emitCVDefRangeDirective(
    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
    codeview::DefRangeRegisterHeader DRHdr) {
  SmallString<20> BytePrefix;
  copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_REGISTER, DRHdr);
  emitCVDefRangeDirective(Ranges, BytePrefix);
}

void MCStreamer::emitCVDefRangeDirective(
    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
    codeview::DefRangeFramePointerRelHeader DRHdr) {
  SmallString<20> BytePrefix;
  copyBytesForDefRange(BytePrefix, codeview::S_DEFRANGE_FRAMEPOINTER_REL,
                       DRHdr);
  emitCVDefRangeDirective(Ranges, BytePrefix);
}

void MCStreamer::emitEHSymAttributes(const MCSymbol *Symbol,
                                     MCSymbol *EHSymbol) {
}

void MCStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) {
  switchSection(getContext().getObjectFileInfo()->getTextSection());
}

void MCStreamer::assignFragment(MCSymbol *Symbol, MCFragment *Fragment) {
  assert(Fragment);
  Symbol->setFragment(Fragment);

  // As we emit symbols into a section, track the order so that they can
  // be sorted upon later. Zero is reserved to mean 'unemitted'.
  SymbolOrdering[Symbol] = 1 + SymbolOrdering.size();
}

void MCStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
  Symbol->redefineIfPossible();

  if (!Symbol->isUndefined() || Symbol->isVariable())
    return getContext().reportError(Loc, "symbol '" + Twine(Symbol->getName()) +
                                             "' is already defined");

  assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
  assert(getCurrentSectionOnly() && "Cannot emit before setting section!");
  assert(!Symbol->getFragment() && "Unexpected fragment on symbol data!");
  assert(Symbol->isUndefined() && "Cannot define a symbol twice!");

  Symbol->setFragment(&getCurrentSectionOnly()->getDummyFragment());

  MCTargetStreamer *TS = getTargetStreamer();
  if (TS)
    TS->emitLabel(Symbol);
}

void MCStreamer::emitConditionalAssignment(MCSymbol *Symbol,
                                           const MCExpr *Value) {}

void MCStreamer::emitCFISections(bool EH, bool Debug) {}

void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) {
  if (!FrameInfoStack.empty() &&
      getCurrentSectionOnly() == FrameInfoStack.back().second)
    return getContext().reportError(
        Loc, "starting new .cfi frame before finishing the previous one");

  MCDwarfFrameInfo Frame;
  Frame.IsSimple = IsSimple;
  emitCFIStartProcImpl(Frame);

  const MCAsmInfo* MAI = Context.getAsmInfo();
  if (MAI) {
    for (const MCCFIInstruction& Inst : MAI->getInitialFrameState()) {
      if (Inst.getOperation() == MCCFIInstruction::OpDefCfa ||
          Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister ||
          Inst.getOperation() == MCCFIInstruction::OpLLVMDefAspaceCfa) {
        Frame.CurrentCfaRegister = Inst.getRegister();
      }
    }
  }

  FrameInfoStack.emplace_back(DwarfFrameInfos.size(), getCurrentSectionOnly());
  DwarfFrameInfos.push_back(Frame);
}

void MCStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
}

void MCStreamer::emitCFIEndProc() {
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  emitCFIEndProcImpl(*CurFrame);
  FrameInfoStack.pop_back();
}

void MCStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
  // Put a dummy non-null value in Frame.End to mark that this frame has been
  // closed.
  Frame.End = (MCSymbol *)1;
}

MCSymbol *MCStreamer::emitCFILabel() {
  // Return a dummy non-null value so that label fields appear filled in when
  // generating textual assembly.
  return (MCSymbol *)1;
}

void MCStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::cfiDefCfa(Label, Register, Offset, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
  CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
}

void MCStreamer::emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::cfiDefCfaOffset(Label, Offset);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createAdjustCfaOffset(Label, Adjustment, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createDefCfaRegister(Label, Register, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
  CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
}

void MCStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
                                         int64_t AddressSpace, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction = MCCFIInstruction::createLLVMDefAspaceCfa(
      Label, Register, Offset, AddressSpace, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
  CurFrame->CurrentCfaRegister = static_cast<unsigned>(Register);
}

void MCStreamer::emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createOffset(Label, Register, Offset, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createRelOffset(Label, Register, Offset, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIPersonality(const MCSymbol *Sym,
                                    unsigned Encoding) {
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Personality = Sym;
  CurFrame->PersonalityEncoding = Encoding;
}

void MCStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Lsda = Sym;
  CurFrame->LsdaEncoding = Encoding;
}

void MCStreamer::emitCFIRememberState(SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createRememberState(Label, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIRestoreState(SMLoc Loc) {
  // FIXME: Error if there is no matching cfi_remember_state.
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createRestoreState(Label, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFISameValue(int64_t Register, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createSameValue(Label, Register, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIRestore(int64_t Register, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createRestore(Label, Register, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIEscape(StringRef Values, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createEscape(Label, Values, Loc, "");
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createGnuArgsSize(Label, Size, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFISignalFrame() {
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->IsSignalFrame = true;
}

void MCStreamer::emitCFIUndefined(int64_t Register, SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createUndefined(Label, Register, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIRegister(int64_t Register1, int64_t Register2,
                                 SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createRegister(Label, Register1, Register2, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIWindowSave(SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction = MCCFIInstruction::createWindowSave(Label, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFINegateRAState(SMLoc Loc) {
  MCSymbol *Label = emitCFILabel();
  MCCFIInstruction Instruction =
      MCCFIInstruction::createNegateRAState(Label, Loc);
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->Instructions.push_back(Instruction);
}

void MCStreamer::emitCFIReturnColumn(int64_t Register) {
  MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo();
  if (!CurFrame)
    return;
  CurFrame->RAReg = Register;
}

WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) {
  const MCAsmInfo *MAI = Context.getAsmInfo();
  if (!MAI->usesWindowsCFI()) {
    getContext().reportError(
        Loc, ".seh_* directives are not supported on this target");
    return nullptr;
  }
  if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) {
    getContext().reportError(
        Loc, ".seh_ directive must appear within an active frame");
    return nullptr;
  }
  return CurrentWinFrameInfo;
}

void MCStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
  const MCAsmInfo *MAI = Context.getAsmInfo();
  if (!MAI->usesWindowsCFI())
    return getContext().reportError(
        Loc, ".seh_* directives are not supported on this target");
  if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End)
    getContext().reportError(
        Loc, "Starting a function before ending the previous one!");

  MCSymbol *StartProc = emitCFILabel();

  CurrentProcWinFrameInfoStartIndex = WinFrameInfos.size();
  WinFrameInfos.emplace_back(
      std::make_unique<WinEH::FrameInfo>(Symbol, StartProc));
  CurrentWinFrameInfo = WinFrameInfos.back().get();
  CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
}

void MCStreamer::emitWinCFIEndProc(SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (CurFrame->ChainedParent)
    getContext().reportError(Loc, "Not all chained regions terminated!");

  MCSymbol *Label = emitCFILabel();
  CurFrame->End = Label;
  if (!CurFrame->FuncletOrFuncEnd)
    CurFrame->FuncletOrFuncEnd = CurFrame->End;

  for (size_t I = CurrentProcWinFrameInfoStartIndex, E = WinFrameInfos.size();
       I != E; ++I)
    emitWindowsUnwindTables(WinFrameInfos[I].get());
  switchSection(CurFrame->TextSection);
}

void MCStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (CurFrame->ChainedParent)
    getContext().reportError(Loc, "Not all chained regions terminated!");

  MCSymbol *Label = emitCFILabel();
  CurFrame->FuncletOrFuncEnd = Label;
}

void MCStreamer::emitWinCFIStartChained(SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;

  MCSymbol *StartProc = emitCFILabel();

  WinFrameInfos.emplace_back(std::make_unique<WinEH::FrameInfo>(
      CurFrame->Function, StartProc, CurFrame));
  CurrentWinFrameInfo = WinFrameInfos.back().get();
  CurrentWinFrameInfo->TextSection = getCurrentSectionOnly();
}

void MCStreamer::emitWinCFIEndChained(SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (!CurFrame->ChainedParent)
    return getContext().reportError(
        Loc, "End of a chained region outside a chained region!");

  MCSymbol *Label = emitCFILabel();

  CurFrame->End = Label;
  CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent);
}

void MCStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
                                  SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (CurFrame->ChainedParent)
    return getContext().reportError(
        Loc, "Chained unwind areas can't have handlers!");
  CurFrame->ExceptionHandler = Sym;
  if (!Except && !Unwind)
    getContext().reportError(Loc, "Don't know what kind of handler this is!");
  if (Unwind)
    CurFrame->HandlesUnwind = true;
  if (Except)
    CurFrame->HandlesExceptions = true;
}

void MCStreamer::emitWinEHHandlerData(SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (CurFrame->ChainedParent)
    getContext().reportError(Loc, "Chained unwind areas can't have handlers!");
}

void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
                                    const MCSymbolRefExpr *To, uint64_t Count) {
}

static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
                                   MCSection *MainCFISec,
                                   const MCSection *TextSec) {
  // If this is the main .text section, use the main unwind info section.
  if (TextSec == Context.getObjectFileInfo()->getTextSection())
    return MainCFISec;

  const auto *TextSecCOFF = cast<MCSectionCOFF>(TextSec);
  auto *MainCFISecCOFF = cast<MCSectionCOFF>(MainCFISec);
  unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextWinCFIID);

  // If this section is COMDAT, this unwind section should be COMDAT associative
  // with its group.
  const MCSymbol *KeySym = nullptr;
  if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) {
    KeySym = TextSecCOFF->getCOMDATSymbol();

    // In a GNU environment, we can't use associative comdats. Instead, do what
    // GCC does, which is to make plain comdat selectany section named like
    // ".[px]data$_Z3foov".
    if (!Context.getAsmInfo()->hasCOFFAssociativeComdats()) {
      std::string SectionName = (MainCFISecCOFF->getName() + "$" +
                                 TextSecCOFF->getName().split('$').second)
                                    .str();
      return Context.getCOFFSection(
          SectionName,
          MainCFISecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT,
          MainCFISecCOFF->getKind(), "", COFF::IMAGE_COMDAT_SELECT_ANY);
    }
  }

  return Context.getAssociativeCOFFSection(MainCFISecCOFF, KeySym, UniqueID);
}

MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) {
  return getWinCFISection(getContext(), &NextWinCFIID,
                          getContext().getObjectFileInfo()->getPDataSection(),
                          TextSec);
}

MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) {
  return getWinCFISection(getContext(), &NextWinCFIID,
                          getContext().getObjectFileInfo()->getXDataSection(),
                          TextSec);
}

void MCStreamer::emitSyntaxDirective() {}

static unsigned encodeSEHRegNum(MCContext &Ctx, MCRegister Reg) {
  return Ctx.getRegisterInfo()->getSEHRegNum(Reg);
}

void MCStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;

  MCSymbol *Label = emitCFILabel();

  WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(
      Label, encodeSEHRegNum(Context, Register));
  CurFrame->Instructions.push_back(Inst);
}

void MCStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset,
                                    SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (CurFrame->LastFrameInst >= 0)
    return getContext().reportError(
        Loc, "frame register and offset can be set at most once");
  if (Offset & 0x0F)
    return getContext().reportError(Loc, "offset is not a multiple of 16");
  if (Offset > 240)
    return getContext().reportError(
        Loc, "frame offset must be less than or equal to 240");

  MCSymbol *Label = emitCFILabel();

  WinEH::Instruction Inst = Win64EH::Instruction::SetFPReg(
      Label, encodeSEHRegNum(getContext(), Register), Offset);
  CurFrame->LastFrameInst = CurFrame->Instructions.size();
  CurFrame->Instructions.push_back(Inst);
}

void MCStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (Size == 0)
    return getContext().reportError(Loc,
                                    "stack allocation size must be non-zero");
  if (Size & 7)
    return getContext().reportError(
        Loc, "stack allocation size is not a multiple of 8");

  MCSymbol *Label = emitCFILabel();

  WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size);
  CurFrame->Instructions.push_back(Inst);
}

void MCStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset,
                                   SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;

  if (Offset & 7)
    return getContext().reportError(
        Loc, "register save offset is not 8 byte aligned");

  MCSymbol *Label = emitCFILabel();

  WinEH::Instruction Inst = Win64EH::Instruction::SaveNonVol(
      Label, encodeSEHRegNum(Context, Register), Offset);
  CurFrame->Instructions.push_back(Inst);
}

void MCStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
                                   SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (Offset & 0x0F)
    return getContext().reportError(Loc, "offset is not a multiple of 16");

  MCSymbol *Label = emitCFILabel();

  WinEH::Instruction Inst = Win64EH::Instruction::SaveXMM(
      Label, encodeSEHRegNum(Context, Register), Offset);
  CurFrame->Instructions.push_back(Inst);
}

void MCStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;
  if (!CurFrame->Instructions.empty())
    return getContext().reportError(
        Loc, "If present, PushMachFrame must be the first UOP");

  MCSymbol *Label = emitCFILabel();

  WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code);
  CurFrame->Instructions.push_back(Inst);
}

void MCStreamer::emitWinCFIEndProlog(SMLoc Loc) {
  WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
  if (!CurFrame)
    return;

  MCSymbol *Label = emitCFILabel();

  CurFrame->PrologEnd = Label;
}

void MCStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {}

void MCStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {}

void MCStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) {}

void MCStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}

void MCStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {}

/// EmitRawText - If this file is backed by an assembly streamer, this dumps
/// the specified string in the output .s file.  This capability is
/// indicated by the hasRawTextSupport() predicate.
void MCStreamer::emitRawTextImpl(StringRef String) {
  // This is not llvm_unreachable for the sake of out of tree backend
  // developers who may not have assembly streamers and should serve as a
  // reminder to not accidentally call EmitRawText in the absence of such.
  report_fatal_error("EmitRawText called on an MCStreamer that doesn't support "
                     "it (target backend is likely missing an AsmStreamer "
                     "implementation)");
}

void MCStreamer::emitRawText(const Twine &T) {
  SmallString<128> Str;
  emitRawTextImpl(T.toStringRef(Str));
}

void MCStreamer::emitWindowsUnwindTables() {}

void MCStreamer::emitWindowsUnwindTables(WinEH::FrameInfo *Frame) {}

void MCStreamer::finish(SMLoc EndLoc) {
  if ((!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) ||
      (!WinFrameInfos.empty() && !WinFrameInfos.back()->End)) {
    getContext().reportError(EndLoc, "Unfinished frame!");
    return;
  }

  MCTargetStreamer *TS = getTargetStreamer();
  if (TS)
    TS->finish();

  finishImpl();
}

void MCStreamer::maybeEmitDwarf64Mark() {
  if (Context.getDwarfFormat() != dwarf::DWARF64)
    return;
  AddComment("DWARF64 Mark");
  emitInt32(dwarf::DW_LENGTH_DWARF64);
}

void MCStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {
  assert(Context.getDwarfFormat() == dwarf::DWARF64 ||
         Length <= dwarf::DW_LENGTH_lo_reserved);
  maybeEmitDwarf64Mark();
  AddComment(Comment);
  emitIntValue(Length, dwarf::getDwarfOffsetByteSize(Context.getDwarfFormat()));
}

MCSymbol *MCStreamer::emitDwarfUnitLength(const Twine &Prefix,
                                          const Twine &Comment) {
  maybeEmitDwarf64Mark();
  AddComment(Comment);
  MCSymbol *Lo = Context.createTempSymbol(Prefix + "_start");
  MCSymbol *Hi = Context.createTempSymbol(Prefix + "_end");

  emitAbsoluteSymbolDiff(
      Hi, Lo, dwarf::getDwarfOffsetByteSize(Context.getDwarfFormat()));
  // emit the begin symbol after we generate the length field.
  emitLabel(Lo);
  // Return the Hi symbol to the caller.
  return Hi;
}

void MCStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {
  // Set the value of the symbol, as we are at the start of the line table.
  emitLabel(StartSym);
}

void MCStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
  visitUsedExpr(*Value);
  Symbol->setVariableValue(Value);

  MCTargetStreamer *TS = getTargetStreamer();
  if (TS)
    TS->emitAssignment(Symbol, Value);
}

void MCTargetStreamer::prettyPrintAsm(MCInstPrinter &InstPrinter,
                                      uint64_t Address, const MCInst &Inst,
                                      const MCSubtargetInfo &STI,
                                      raw_ostream &OS) {
  InstPrinter.printInst(&Inst, Address, "", STI, OS);
}

void MCStreamer::visitUsedSymbol(const MCSymbol &Sym) {
}

void MCStreamer::visitUsedExpr(const MCExpr &Expr) {
  switch (Expr.getKind()) {
  case MCExpr::Target:
    cast<MCTargetExpr>(Expr).visitUsedExpr(*this);
    break;

  case MCExpr::Constant:
    break;

  case MCExpr::Binary: {
    const MCBinaryExpr &BE = cast<MCBinaryExpr>(Expr);
    visitUsedExpr(*BE.getLHS());
    visitUsedExpr(*BE.getRHS());
    break;
  }

  case MCExpr::SymbolRef:
    visitUsedSymbol(cast<MCSymbolRefExpr>(Expr).getSymbol());
    break;

  case MCExpr::Unary:
    visitUsedExpr(*cast<MCUnaryExpr>(Expr).getSubExpr());
    break;
  }
}

void MCStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &) {
  // Scan for values.
  for (unsigned i = Inst.getNumOperands(); i--;)
    if (Inst.getOperand(i).isExpr())
      visitUsedExpr(*Inst.getOperand(i).getExpr());
}

void MCStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
                                 uint64_t Attr, uint64_t Discriminator,
                                 const MCPseudoProbeInlineStack &InlineStack,
                                 MCSymbol *FnSym) {
  auto &Context = getContext();

  // Create a symbol at in the current section for use in the probe.
  MCSymbol *ProbeSym = Context.createTempSymbol();

  // Set the value of the symbol to use for the MCPseudoProbe.
  emitLabel(ProbeSym);

  // Create a (local) probe entry with the symbol.
  MCPseudoProbe Probe(ProbeSym, Guid, Index, Type, Attr, Discriminator);

  // Add the probe entry to this section's entries.
  Context.getMCPseudoProbeTable().getProbeSections().addPseudoProbe(
      FnSym, Probe, InlineStack);
}

void MCStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
                                        unsigned Size) {
  // Get the Hi-Lo expression.
  const MCExpr *Diff =
      MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context),
                              MCSymbolRefExpr::create(Lo, Context), Context);

  const MCAsmInfo *MAI = Context.getAsmInfo();
  if (!MAI->doesSetDirectiveSuppressReloc()) {
    emitValue(Diff, Size);
    return;
  }

  // Otherwise, emit with .set (aka assignment).
  MCSymbol *SetLabel = Context.createTempSymbol("set");
  emitAssignment(SetLabel, Diff);
  emitSymbolValue(SetLabel, Size);
}

void MCStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
                                                 const MCSymbol *Lo) {
  // Get the Hi-Lo expression.
  const MCExpr *Diff =
      MCBinaryExpr::createSub(MCSymbolRefExpr::create(Hi, Context),
                              MCSymbolRefExpr::create(Lo, Context), Context);

  emitULEB128Value(Diff);
}

void MCStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {}
void MCStreamer::emitThumbFunc(MCSymbol *Func) {}
void MCStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
void MCStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {
  llvm_unreachable("this directive only supported on COFF targets");
}
void MCStreamer::endCOFFSymbolDef() {
  llvm_unreachable("this directive only supported on COFF targets");
}
void MCStreamer::emitFileDirective(StringRef Filename) {}
void MCStreamer::emitFileDirective(StringRef Filename, StringRef CompilerVerion,
                                   StringRef TimeStamp, StringRef Description) {
}
void MCStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
  llvm_unreachable("this directive only supported on COFF targets");
}
void MCStreamer::emitCOFFSymbolType(int Type) {
  llvm_unreachable("this directive only supported on COFF targets");
}
void MCStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
                                            MCSymbol *CsectSym,
                                            Align Alignment) {
  llvm_unreachable("this directive only supported on XCOFF targets");
}

void MCStreamer::emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
                                                      MCSymbolAttr Linkage,
                                                      MCSymbolAttr Visibility) {
  llvm_unreachable("emitXCOFFSymbolLinkageWithVisibility is only supported on "
                   "XCOFF targets");
}

void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
                                          StringRef Rename) {}

void MCStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
  llvm_unreachable("emitXCOFFRefDirective is only supported on XCOFF targets");
}

void MCStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
                                          const MCSymbol *Trap,
                                          unsigned Lang, unsigned Reason,
                                          unsigned FunctionSize,
                                          bool hasDebug) {
  report_fatal_error("emitXCOFFExceptDirective is only supported on "
                     "XCOFF targets");
}

void MCStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
  llvm_unreachable("emitXCOFFCInfoSym is only supported on"
                   "XCOFF targets");
}

void MCStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
void MCStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
                                        StringRef Name, bool KeepOriginalSym) {}
void MCStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                       Align ByteAlignment) {}
void MCStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
                                uint64_t Size, Align ByteAlignment) {}
void MCStreamer::changeSection(MCSection *, const MCExpr *) {}
void MCStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
void MCStreamer::emitBytes(StringRef Data) {}
void MCStreamer::emitBinaryData(StringRef Data) { emitBytes(Data); }
void MCStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
  visitUsedExpr(*Value);
}
void MCStreamer::emitULEB128Value(const MCExpr *Value) {}
void MCStreamer::emitSLEB128Value(const MCExpr *Value) {}
void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {}
void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
                          SMLoc Loc) {}
void MCStreamer::emitValueToAlignment(Align Alignment, int64_t Value,
                                      unsigned ValueSize,
                                      unsigned MaxBytesToEmit) {}
void MCStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI,
                                   unsigned MaxBytesToEmit) {}
void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
                                   SMLoc Loc) {}
void MCStreamer::emitBundleAlignMode(Align Alignment) {}
void MCStreamer::emitBundleLock(bool AlignToEnd) {}
void MCStreamer::finishImpl() {}
void MCStreamer::emitBundleUnlock() {}

void MCStreamer::switchSection(MCSection *Section, const MCExpr *Subsection) {
  assert(Section && "Cannot switch to a null section!");
  MCSectionSubPair curSection = SectionStack.back().first;
  SectionStack.back().second = curSection;
  if (MCSectionSubPair(Section, Subsection) != curSection) {
    changeSection(Section, Subsection);
    SectionStack.back().first = MCSectionSubPair(Section, Subsection);
    assert(!Section->hasEnded() && "Section already ended");
    MCSymbol *Sym = Section->getBeginSymbol();
    if (Sym && !Sym->isInSection())
      emitLabel(Sym);
  }
}

MCSymbol *MCStreamer::endSection(MCSection *Section) {
  // TODO: keep track of the last subsection so that this symbol appears in the
  // correct place.
  MCSymbol *Sym = Section->getEndSymbol(Context);
  if (Sym->isInSection())
    return Sym;

  switchSection(Section);
  emitLabel(Sym);
  return Sym;
}

static VersionTuple
targetVersionOrMinimumSupportedOSVersion(const Triple &Target,
                                         VersionTuple TargetVersion) {
  VersionTuple Min = Target.getMinimumSupportedOSVersion();
  return !Min.empty() && Min > TargetVersion ? Min : TargetVersion;
}

static MCVersionMinType
getMachoVersionMinLoadCommandType(const Triple &Target) {
  assert(Target.isOSDarwin() && "expected a darwin OS");
  switch (Target.getOS()) {
  case Triple::MacOSX:
  case Triple::Darwin:
    return MCVM_OSXVersionMin;
  case Triple::IOS:
    assert(!Target.isMacCatalystEnvironment() &&
           "mac Catalyst should use LC_BUILD_VERSION");
    return MCVM_IOSVersionMin;
  case Triple::TvOS:
    return MCVM_TvOSVersionMin;
  case Triple::WatchOS:
    return MCVM_WatchOSVersionMin;
  default:
    break;
  }
  llvm_unreachable("unexpected OS type");
}

static VersionTuple getMachoBuildVersionSupportedOS(const Triple &Target) {
  assert(Target.isOSDarwin() && "expected a darwin OS");
  switch (Target.getOS()) {
  case Triple::MacOSX:
  case Triple::Darwin:
    return VersionTuple(10, 14);
  case Triple::IOS:
    // Mac Catalyst always uses the build version load command.
    if (Target.isMacCatalystEnvironment())
      return VersionTuple();
    [[fallthrough]];
  case Triple::TvOS:
    return VersionTuple(12);
  case Triple::WatchOS:
    return VersionTuple(5);
  case Triple::DriverKit:
    // DriverKit always uses the build version load command.
    return VersionTuple();
  case Triple::XROS:
    // XROS always uses the build version load command.
    return VersionTuple();
  default:
    break;
  }
  llvm_unreachable("unexpected OS type");
}

static MachO::PlatformType
getMachoBuildVersionPlatformType(const Triple &Target) {
  assert(Target.isOSDarwin() && "expected a darwin OS");
  switch (Target.getOS()) {
  case Triple::MacOSX:
  case Triple::Darwin:
    return MachO::PLATFORM_MACOS;
  case Triple::IOS:
    if (Target.isMacCatalystEnvironment())
      return MachO::PLATFORM_MACCATALYST;
    return Target.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR
                                           : MachO::PLATFORM_IOS;
  case Triple::TvOS:
    return Target.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR
                                           : MachO::PLATFORM_TVOS;
  case Triple::WatchOS:
    return Target.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR
                                           : MachO::PLATFORM_WATCHOS;
  case Triple::DriverKit:
    return MachO::PLATFORM_DRIVERKIT;
  case Triple::XROS:
    return Target.isSimulatorEnvironment() ? MachO::PLATFORM_XROS_SIMULATOR
                                           : MachO::PLATFORM_XROS;
  default:
    break;
  }
  llvm_unreachable("unexpected OS type");
}

void MCStreamer::emitVersionForTarget(
    const Triple &Target, const VersionTuple &SDKVersion,
    const Triple *DarwinTargetVariantTriple,
    const VersionTuple &DarwinTargetVariantSDKVersion) {
  if (!Target.isOSBinFormatMachO() || !Target.isOSDarwin())
    return;
  // Do we even know the version?
  if (Target.getOSMajorVersion() == 0)
    return;

  VersionTuple Version;
  switch (Target.getOS()) {
  case Triple::MacOSX:
  case Triple::Darwin:
    Target.getMacOSXVersion(Version);
    break;
  case Triple::IOS:
  case Triple::TvOS:
    Version = Target.getiOSVersion();
    break;
  case Triple::WatchOS:
    Version = Target.getWatchOSVersion();
    break;
  case Triple::DriverKit:
    Version = Target.getDriverKitVersion();
    break;
  case Triple::XROS:
    Version = Target.getOSVersion();
    break;
  default:
    llvm_unreachable("unexpected OS type");
  }
  assert(Version.getMajor() != 0 && "A non-zero major version is expected");
  auto LinkedTargetVersion =
      targetVersionOrMinimumSupportedOSVersion(Target, Version);
  auto BuildVersionOSVersion = getMachoBuildVersionSupportedOS(Target);
  bool ShouldEmitBuildVersion = false;
  if (BuildVersionOSVersion.empty() ||
      LinkedTargetVersion >= BuildVersionOSVersion) {
    if (Target.isMacCatalystEnvironment() && DarwinTargetVariantTriple &&
        DarwinTargetVariantTriple->isMacOSX()) {
      emitVersionForTarget(*DarwinTargetVariantTriple,
                           DarwinTargetVariantSDKVersion,
                           /*DarwinTargetVariantTriple=*/nullptr,
                           /*DarwinTargetVariantSDKVersion=*/VersionTuple());
      emitDarwinTargetVariantBuildVersion(
          getMachoBuildVersionPlatformType(Target),
          LinkedTargetVersion.getMajor(),
          LinkedTargetVersion.getMinor().value_or(0),
          LinkedTargetVersion.getSubminor().value_or(0), SDKVersion);
      return;
    }
    emitBuildVersion(getMachoBuildVersionPlatformType(Target),
                     LinkedTargetVersion.getMajor(),
                     LinkedTargetVersion.getMinor().value_or(0),
                     LinkedTargetVersion.getSubminor().value_or(0), SDKVersion);
    ShouldEmitBuildVersion = true;
  }

  if (const Triple *TVT = DarwinTargetVariantTriple) {
    if (Target.isMacOSX() && TVT->isMacCatalystEnvironment()) {
      auto TVLinkedTargetVersion =
          targetVersionOrMinimumSupportedOSVersion(*TVT, TVT->getiOSVersion());
      emitDarwinTargetVariantBuildVersion(
          getMachoBuildVersionPlatformType(*TVT),
          TVLinkedTargetVersion.getMajor(),
          TVLinkedTargetVersion.getMinor().value_or(0),
          TVLinkedTargetVersion.getSubminor().value_or(0),
          DarwinTargetVariantSDKVersion);
    }
  }

  if (ShouldEmitBuildVersion)
    return;

  emitVersionMin(getMachoVersionMinLoadCommandType(Target),
                 LinkedTargetVersion.getMajor(),
                 LinkedTargetVersion.getMinor().value_or(0),
                 LinkedTargetVersion.getSubminor().value_or(0), SDKVersion);
}
