//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/MC/MCDwarf.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

// Given a special op, return the address skip amount (in units of
// DWARF2_LINE_MIN_INSN_LENGTH.
#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)

// The maximum address skip amount that can be encoded with a special op.
#define MAX_SPECIAL_ADDR_DELTA         SPECIAL_ADDR(255)

// First special line opcode - leave room for the standard opcodes.
// Note: If you want to change this, you'll have to update the
// "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit().
#define DWARF2_LINE_OPCODE_BASE         13

// Minimum line offset in a special line info. opcode.  This value
// was chosen to give a reasonable range of values.
#define DWARF2_LINE_BASE                -5

// Range of line offsets in a special line info. opcode.
#define DWARF2_LINE_RANGE               14

// Define the architecture-dependent minimum instruction length (in bytes).
// This value should be rather too small than too big.
#define DWARF2_LINE_MIN_INSN_LENGTH     1

// Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting,
// this routine is a nop and will be optimized away.
static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) {
  if (DWARF2_LINE_MIN_INSN_LENGTH == 1)
    return AddrDelta;
  if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) {
    // TODO: report this error, but really only once.
    ;
  }
  return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH;
}

//
// This is called when an instruction is assembled into the specified section
// and if there is information from the last .loc directive that has yet to have
// a line entry made for it is made.
//
void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) {
  if (!MCOS->getContext().getDwarfLocSeen())
    return;

  // Create a symbol at in the current section for use in the line entry.
  MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol();
  // Set the value of the symbol to use for the MCLineEntry.
  MCOS->EmitLabel(LineSym);

  // Get the current .loc info saved in the context.
  const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();

  // Create a (local) line entry with the symbol and the current .loc info.
  MCLineEntry LineEntry(LineSym, DwarfLoc);

  // clear DwarfLocSeen saying the current .loc info is now used.
  MCOS->getContext().ClearDwarfLocSeen();

  // Get the MCLineSection for this section, if one does not exist for this
  // section create it.
  const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
    MCOS->getContext().getMCLineSections();
  MCLineSection *LineSection = MCLineSections.lookup(Section);
  if (!LineSection) {
    // Create a new MCLineSection.  This will be deleted after the dwarf line
    // table is created using it by iterating through the MCLineSections
    // DenseMap.
    LineSection = new MCLineSection;
    // Save a pointer to the new LineSection into the MCLineSections DenseMap.
    MCOS->getContext().addMCLineSection(Section, LineSection);
  }

  // Add the line entry to this section's entries.
  LineSection->addLineEntry(LineEntry,
                            MCOS->getContext().getDwarfCompileUnitID());
}

//
// This helper routine returns an expression of End - Start + IntVal .
//
static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
                                                  const MCSymbol &Start,
                                                  const MCSymbol &End,
                                                  int IntVal) {
  MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
  const MCExpr *Res =
    MCSymbolRefExpr::Create(&End, Variant, MCOS.getContext());
  const MCExpr *RHS =
    MCSymbolRefExpr::Create(&Start, Variant, MCOS.getContext());
  const MCExpr *Res1 =
    MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext());
  const MCExpr *Res2 =
    MCConstantExpr::Create(IntVal, MCOS.getContext());
  const MCExpr *Res3 =
    MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext());
  return Res3;
}

//
// This emits the Dwarf line table for the specified section from the entries
// in the LineSection.
//
static inline void EmitDwarfLineTable(MCStreamer *MCOS,
                                      const MCSection *Section,
                                      const MCLineSection *LineSection,
                                      unsigned CUID) {
  // This LineSection does not contain any LineEntry for the given Compile Unit.
  if (!LineSection->containEntriesForID(CUID))
    return;

  unsigned FileNum = 1;
  unsigned LastLine = 1;
  unsigned Column = 0;
  unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
  unsigned Isa = 0;
  MCSymbol *LastLabel = NULL;

  // Loop through each MCLineEntry and encode the dwarf line number table.
  for (MCLineSection::const_iterator
         it = LineSection->getMCLineEntries(CUID).begin(),
         ie = LineSection->getMCLineEntries(CUID).end(); it != ie; ++it) {

    if (FileNum != it->getFileNum()) {
      FileNum = it->getFileNum();
      MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
      MCOS->EmitULEB128IntValue(FileNum);
    }
    if (Column != it->getColumn()) {
      Column = it->getColumn();
      MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
      MCOS->EmitULEB128IntValue(Column);
    }
    if (Isa != it->getIsa()) {
      Isa = it->getIsa();
      MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
      MCOS->EmitULEB128IntValue(Isa);
    }
    if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
      Flags = it->getFlags();
      MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1);
    }
    if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK)
      MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1);
    if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END)
      MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
    if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
      MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);

    int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine;
    MCSymbol *Label = it->getLabel();

    // At this point we want to emit/create the sequence to encode the delta in
    // line numbers and the increment of the address from the previous Label
    // and the current Label.
    const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo();
    MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
                                   asmInfo.getPointerSize());

    LastLine = it->getLine();
    LastLabel = Label;
  }

  // Emit a DW_LNE_end_sequence for the end of the section.
  // Using the pointer Section create a temporary label at the end of the
  // section and use that and the LastLabel to compute the address delta
  // and use INT64_MAX as the line delta which is the signal that this is
  // actually a DW_LNE_end_sequence.

  // Switch to the section to be able to create a symbol at its end.
  MCOS->SwitchSection(Section);

  MCContext &context = MCOS->getContext();
  // Create a symbol at the end of the section.
  MCSymbol *SectionEnd = context.CreateTempSymbol();
  // Set the value of the symbol, as we are at the end of the section.
  MCOS->EmitLabel(SectionEnd);

  // Switch back the dwarf line section.
  MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());

  const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo();
  MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
                                 asmInfo.getPointerSize());
}

//
// This emits the Dwarf file and the line tables.
//
const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) {
  MCContext &context = MCOS->getContext();
  // Switch to the section where the table will be emitted into.
  MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());

  const DenseMap<unsigned, MCSymbol *> &MCLineTableSymbols =
    MCOS->getContext().getMCLineTableSymbols();
  // CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does
  // not exist, CUID will be 0 and MCLineTableSymbols will be empty.
  // Handle Compile Unit 0, the line table start symbol is the section symbol.
  const MCSymbol *LineStartSym = EmitCU(MCOS, 0);
  // Handle the rest of the Compile Units.
  for (unsigned Is = 1, Ie = MCLineTableSymbols.size(); Is < Ie; Is++)
    EmitCU(MCOS, Is);

  // Now delete the MCLineSections that were created in MCLineEntry::Make()
  // and used to emit the line table.
  const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
    MCOS->getContext().getMCLineSections();
  for (DenseMap<const MCSection *, MCLineSection *>::const_iterator it =
       MCLineSections.begin(), ie = MCLineSections.end(); it != ie;
       ++it)
    delete it->second;

  return LineStartSym;
}

const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) {
  MCContext &context = MCOS->getContext();

  // Create a symbol at the beginning of the line table.
  MCSymbol *LineStartSym = MCOS->getContext().getMCLineTableSymbol(CUID);
  if (!LineStartSym)
    LineStartSym = context.CreateTempSymbol();
  // Set the value of the symbol, as we are at the start of the line table.
  MCOS->EmitLabel(LineStartSym);

  // Create a symbol for the end of the section (to be set when we get there).
  MCSymbol *LineEndSym = context.CreateTempSymbol();

  // The first 4 bytes is the total length of the information for this
  // compilation unit (not including these 4 bytes for the length).
  MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym,4),
                     4);

  // Next 2 bytes is the Version, which is Dwarf 2.
  MCOS->EmitIntValue(2, 2);

  // Create a symbol for the end of the prologue (to be set when we get there).
  MCSymbol *ProEndSym = context.CreateTempSymbol(); // Lprologue_end

  // Length of the prologue, is the next 4 bytes.  Which is the start of the
  // section to the end of the prologue.  Not including the 4 bytes for the
  // total length, the 2 bytes for the version, and these 4 bytes for the
  // length of the prologue.
  MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym,
                                           (4 + 2 + 4)), 4, 0);

  // Parameters of the state machine, are next.
  MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1);
  MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1);
  MCOS->EmitIntValue(DWARF2_LINE_BASE, 1);
  MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1);
  MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1);

  // Standard opcode lengths
  MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy
  MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc
  MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line
  MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file
  MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column
  MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt
  MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block
  MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc
  MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc
  MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end
  MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin
  MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa

  // Put out the directory and file tables.

  // First the directory table.
  const std::vector<StringRef> &MCDwarfDirs =
    context.getMCDwarfDirs(CUID);
  for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
    MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName
    MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
  }
  MCOS->EmitIntValue(0, 1); // Terminate the directory list

  // Second the file table.
  const std::vector<MCDwarfFile *> &MCDwarfFiles =
    MCOS->getContext().getMCDwarfFiles(CUID);
  for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
    MCOS->EmitBytes(MCDwarfFiles[i]->getName()); // FileName
    MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
    // the Directory num
    MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex());
    MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
    MCOS->EmitIntValue(0, 1); // filesize (always 0)
  }
  MCOS->EmitIntValue(0, 1); // Terminate the file list

  // This is the end of the prologue, so set the value of the symbol at the
  // end of the prologue (that was used in a previous expression).
  MCOS->EmitLabel(ProEndSym);

  // Put out the line tables.
  const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
    MCOS->getContext().getMCLineSections();
  const std::vector<const MCSection *> &MCLineSectionOrder =
    MCOS->getContext().getMCLineSectionOrder();
  for (std::vector<const MCSection*>::const_iterator it =
         MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie;
       ++it) {
    const MCSection *Sec = *it;
    const MCLineSection *Line = MCLineSections.lookup(Sec);
    EmitDwarfLineTable(MCOS, Sec, Line, CUID);
  }

  if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines()
      && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) {
    // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures
    // it requires:
    // total_length >= prologue_length + 10
    // We are 4 bytes short, since we have total_length = 51 and
    // prologue_length = 45

    // The regular end_sequence should be sufficient.
    MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0);
  }

  // This is the end of the section, so set the value of the symbol at the end
  // of this section (that was used in a previous expression).
  MCOS->EmitLabel(LineEndSym);

  return LineStartSym;
}

/// Utility function to write the encoding to an object writer.
void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta,
                            uint64_t AddrDelta) {
  SmallString<256> Tmp;
  raw_svector_ostream OS(Tmp);
  MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
  OW->WriteBytes(OS.str());
}

/// Utility function to emit the encoding to a streamer.
void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta,
                           uint64_t AddrDelta) {
  SmallString<256> Tmp;
  raw_svector_ostream OS(Tmp);
  MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
  MCOS->EmitBytes(OS.str());
}

/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta,
                             raw_ostream &OS) {
  uint64_t Temp, Opcode;
  bool NeedCopy = false;

  // Scale the address delta by the minimum instruction length.
  AddrDelta = ScaleAddrDelta(AddrDelta);

  // A LineDelta of INT64_MAX is a signal that this is actually a
  // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the
  // end_sequence to emit the matrix entry.
  if (LineDelta == INT64_MAX) {
    if (AddrDelta == MAX_SPECIAL_ADDR_DELTA)
      OS << char(dwarf::DW_LNS_const_add_pc);
    else {
      OS << char(dwarf::DW_LNS_advance_pc);
      encodeULEB128(AddrDelta, OS);
    }
    OS << char(dwarf::DW_LNS_extended_op);
    OS << char(1);
    OS << char(dwarf::DW_LNE_end_sequence);
    return;
  }

  // Bias the line delta by the base.
  Temp = LineDelta - DWARF2_LINE_BASE;

  // If the line increment is out of range of a special opcode, we must encode
  // it with DW_LNS_advance_line.
  if (Temp >= DWARF2_LINE_RANGE) {
    OS << char(dwarf::DW_LNS_advance_line);
    encodeSLEB128(LineDelta, OS);

    LineDelta = 0;
    Temp = 0 - DWARF2_LINE_BASE;
    NeedCopy = true;
  }

  // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode.
  if (LineDelta == 0 && AddrDelta == 0) {
    OS << char(dwarf::DW_LNS_copy);
    return;
  }

  // Bias the opcode by the special opcode base.
  Temp += DWARF2_LINE_OPCODE_BASE;

  // Avoid overflow when addr_delta is large.
  if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) {
    // Try using a special opcode.
    Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE;
    if (Opcode <= 255) {
      OS << char(Opcode);
      return;
    }

    // Try using DW_LNS_const_add_pc followed by special op.
    Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
    if (Opcode <= 255) {
      OS << char(dwarf::DW_LNS_const_add_pc);
      OS << char(Opcode);
      return;
    }
  }

  // Otherwise use DW_LNS_advance_pc.
  OS << char(dwarf::DW_LNS_advance_pc);
  encodeULEB128(AddrDelta, OS);

  if (NeedCopy)
    OS << char(dwarf::DW_LNS_copy);
  else
    OS << char(Temp);
}

void MCDwarfFile::print(raw_ostream &OS) const {
  OS << '"' << getName() << '"';
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void MCDwarfFile::dump() const {
  print(dbgs());
}
#endif

// Utility function to write a tuple for .debug_abbrev.
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
  MCOS->EmitULEB128IntValue(Name);
  MCOS->EmitULEB128IntValue(Form);
}

// When generating dwarf for assembly source files this emits
// the data for .debug_abbrev section which contains three DIEs.
static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
  MCContext &context = MCOS->getContext();
  MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());

  // DW_TAG_compile_unit DIE abbrev (1).
  MCOS->EmitULEB128IntValue(1);
  MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
  MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
  EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4);
  EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
  EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
  EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
  EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
  StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
  if (!DwarfDebugFlags.empty())
    EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
  EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
  EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
  EmitAbbrev(MCOS, 0, 0);

  // DW_TAG_label DIE abbrev (2).
  MCOS->EmitULEB128IntValue(2);
  MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label);
  MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
  EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
  EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
  EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
  EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
  EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag);
  EmitAbbrev(MCOS, 0, 0);

  // DW_TAG_unspecified_parameters DIE abbrev (3).
  MCOS->EmitULEB128IntValue(3);
  MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters);
  MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1);
  EmitAbbrev(MCOS, 0, 0);

  // Terminate the abbreviations for this compilation unit.
  MCOS->EmitIntValue(0, 1);
}

// When generating dwarf for assembly source files this emits the data for
// .debug_aranges section.  Which contains a header and a table of pairs of
// PointerSize'ed values for the address and size of section(s) with line table
// entries (just the default .text in our case) and a terminating pair of zeros.
static void EmitGenDwarfAranges(MCStreamer *MCOS,
                                const MCSymbol *InfoSectionSymbol) {
  MCContext &context = MCOS->getContext();

  // Create a symbol at the end of the section that we are creating the dwarf
  // debugging info to use later in here as part of the expression to calculate
  // the size of the section for the table.
  MCOS->SwitchSection(context.getGenDwarfSection());
  MCSymbol *SectionEndSym = context.CreateTempSymbol();
  MCOS->EmitLabel(SectionEndSym);
  context.setGenDwarfSectionEndSym(SectionEndSym);

  MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());

  // This will be the length of the .debug_aranges section, first account for
  // the size of each item in the header (see below where we emit these items).
  int Length = 4 + 2 + 4 + 1 + 1;

  // Figure the padding after the header before the table of address and size
  // pairs who's values are PointerSize'ed.
  const MCAsmInfo &asmInfo = context.getAsmInfo();
  int AddrSize = asmInfo.getPointerSize();
  int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
  if (Pad == 2 * AddrSize)
    Pad = 0;
  Length += Pad;

  // Add the size of the pair of PointerSize'ed values for the address and size
  // of the one default .text section we have in the table.
  Length += 2 * AddrSize;
  // And the pair of terminating zeros.
  Length += 2 * AddrSize;


  // Emit the header for this section.
  // The 4 byte length not including the 4 byte value for the length.
  MCOS->EmitIntValue(Length - 4, 4);
  // The 2 byte version, which is 2.
  MCOS->EmitIntValue(2, 2);
  // The 4 byte offset to the compile unit in the .debug_info from the start
  // of the .debug_info.
  if (InfoSectionSymbol)
    MCOS->EmitSymbolValue(InfoSectionSymbol, 4);
  else
    MCOS->EmitIntValue(0, 4);
  // The 1 byte size of an address.
  MCOS->EmitIntValue(AddrSize, 1);
  // The 1 byte size of a segment descriptor, we use a value of zero.
  MCOS->EmitIntValue(0, 1);
  // Align the header with the padding if needed, before we put out the table.
  for(int i = 0; i < Pad; i++)
    MCOS->EmitIntValue(0, 1);

  // Now emit the table of pairs of PointerSize'ed values for the section(s)
  // address and size, in our case just the one default .text section.
  const MCExpr *Addr = MCSymbolRefExpr::Create(
    context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context);
  const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
    *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0);
  MCOS->EmitAbsValue(Addr, AddrSize);
  MCOS->EmitAbsValue(Size, AddrSize);

  // And finally the pair of terminating zeros.
  MCOS->EmitIntValue(0, AddrSize);
  MCOS->EmitIntValue(0, AddrSize);
}

// When generating dwarf for assembly source files this emits the data for
// .debug_info section which contains three parts.  The header, the compile_unit
// DIE and a list of label DIEs.
static void EmitGenDwarfInfo(MCStreamer *MCOS,
                             const MCSymbol *AbbrevSectionSymbol,
                             const MCSymbol *LineSectionSymbol) {
  MCContext &context = MCOS->getContext();

  MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());

  // Create a symbol at the start and end of this section used in here for the
  // expression to calculate the length in the header.
  MCSymbol *InfoStart = context.CreateTempSymbol();
  MCOS->EmitLabel(InfoStart);
  MCSymbol *InfoEnd = context.CreateTempSymbol();

  // First part: the header.

  // The 4 byte total length of the information for this compilation unit, not
  // including these 4 bytes.
  const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4);
  MCOS->EmitAbsValue(Length, 4);

  // The 2 byte DWARF version, which is 2.
  MCOS->EmitIntValue(2, 2);

  // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev,
  // it is at the start of that section so this is zero.
  if (AbbrevSectionSymbol) {
    MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4);
  } else {
    MCOS->EmitIntValue(0, 4);
  }

  const MCAsmInfo &asmInfo = context.getAsmInfo();
  int AddrSize = asmInfo.getPointerSize();
  // The 1 byte size of an address.
  MCOS->EmitIntValue(AddrSize, 1);

  // Second part: the compile_unit DIE.

  // The DW_TAG_compile_unit DIE abbrev (1).
  MCOS->EmitULEB128IntValue(1);

  // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section,
  // which is at the start of that section so this is zero.
  if (LineSectionSymbol) {
    MCOS->EmitSymbolValue(LineSectionSymbol, 4);
  } else {
    MCOS->EmitIntValue(0, 4);
  }

  // AT_low_pc, the first address of the default .text section.
  const MCExpr *Start = MCSymbolRefExpr::Create(
    context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context);
  MCOS->EmitAbsValue(Start, AddrSize);

  // AT_high_pc, the last address of the default .text section.
  const MCExpr *End = MCSymbolRefExpr::Create(
    context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context);
  MCOS->EmitAbsValue(End, AddrSize);

  // AT_name, the name of the source file.  Reconstruct from the first directory
  // and file table entries.
  const std::vector<StringRef> &MCDwarfDirs =
    context.getMCDwarfDirs();
  if (MCDwarfDirs.size() > 0) {
    MCOS->EmitBytes(MCDwarfDirs[0]);
    MCOS->EmitBytes("/");
  }
  const std::vector<MCDwarfFile *> &MCDwarfFiles =
    MCOS->getContext().getMCDwarfFiles();
  MCOS->EmitBytes(MCDwarfFiles[1]->getName());
  MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.

  // AT_comp_dir, the working directory the assembly was done in.
  MCOS->EmitBytes(context.getCompilationDir());
  MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.

  // AT_APPLE_flags, the command line arguments of the assembler tool.
  StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
  if (!DwarfDebugFlags.empty()){
    MCOS->EmitBytes(DwarfDebugFlags);
    MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
  }

  // AT_producer, the version of the assembler tool.
  StringRef DwarfDebugProducer = context.getDwarfDebugProducer();
  if (!DwarfDebugProducer.empty()){
    MCOS->EmitBytes(DwarfDebugProducer);
  }
  else {
    MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM "));
    MCOS->EmitBytes(StringRef(PACKAGE_VERSION));
    MCOS->EmitBytes(StringRef(")"));
  }
  MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.

  // AT_language, a 4 byte value.  We use DW_LANG_Mips_Assembler as the dwarf2
  // draft has no standard code for assembler.
  MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2);

  // Third part: the list of label DIEs.

  // Loop on saved info for dwarf labels and create the DIEs for them.
  const std::vector<const MCGenDwarfLabelEntry *> &Entries =
    MCOS->getContext().getMCGenDwarfLabelEntries();
  for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it =
       Entries.begin(), ie = Entries.end(); it != ie;
       ++it) {
    const MCGenDwarfLabelEntry *Entry = *it;

    // The DW_TAG_label DIE abbrev (2).
    MCOS->EmitULEB128IntValue(2);

    // AT_name, of the label without any leading underbar.
    MCOS->EmitBytes(Entry->getName());
    MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.

    // AT_decl_file, index into the file table.
    MCOS->EmitIntValue(Entry->getFileNumber(), 4);

    // AT_decl_line, source line number.
    MCOS->EmitIntValue(Entry->getLineNumber(), 4);

    // AT_low_pc, start address of the label.
    const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry->getLabel(),
                                             MCSymbolRefExpr::VK_None, context);
    MCOS->EmitAbsValue(AT_low_pc, AddrSize);

    // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype.
    MCOS->EmitIntValue(0, 1);

    // The DW_TAG_unspecified_parameters DIE abbrev (3).
    MCOS->EmitULEB128IntValue(3);

    // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's.
    MCOS->EmitIntValue(0, 1);
  }
  // Deallocate the MCGenDwarfLabelEntry classes that saved away the info
  // for the dwarf labels.
  for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it =
       Entries.begin(), ie = Entries.end(); it != ie;
       ++it) {
    const MCGenDwarfLabelEntry *Entry = *it;
    delete Entry;
  }

  // Add the NULL DIE terminating the Compile Unit DIE's.
  MCOS->EmitIntValue(0, 1);

  // Now set the value of the symbol at the end of the info section.
  MCOS->EmitLabel(InfoEnd);
}

//
// When generating dwarf for assembly source files this emits the Dwarf
// sections.
//
void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) {
  // Create the dwarf sections in this order (.debug_line already created).
  MCContext &context = MCOS->getContext();
  const MCAsmInfo &AsmInfo = context.getAsmInfo();
  bool CreateDwarfSectionSymbols =
      AsmInfo.doesDwarfUseRelocationsAcrossSections();
  if (!CreateDwarfSectionSymbols)
    LineSectionSymbol = NULL;
  MCSymbol *AbbrevSectionSymbol = NULL;
  MCSymbol *InfoSectionSymbol = NULL;
  MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
  if (CreateDwarfSectionSymbols) {
    InfoSectionSymbol = context.CreateTempSymbol();
    MCOS->EmitLabel(InfoSectionSymbol);
  }
  MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
  if (CreateDwarfSectionSymbols) {
    AbbrevSectionSymbol = context.CreateTempSymbol();
    MCOS->EmitLabel(AbbrevSectionSymbol);
  }
  MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());

  // If there are no line table entries then do not emit any section contents.
  if (context.getMCLineSections().empty())
    return;

  // Output the data for .debug_aranges section.
  EmitGenDwarfAranges(MCOS, InfoSectionSymbol);

  // Output the data for .debug_abbrev section.
  EmitGenDwarfAbbrev(MCOS);

  // Output the data for .debug_info section.
  EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol);
}

//
// When generating dwarf for assembly source files this is called when symbol
// for a label is created.  If this symbol is not a temporary and is in the
// section that dwarf is being generated for, save the needed info to create
// a dwarf label.
//
void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
                                     SourceMgr &SrcMgr, SMLoc &Loc) {
  // We won't create dwarf labels for temporary symbols or symbols not in
  // the default text.
  if (Symbol->isTemporary())
    return;
  MCContext &context = MCOS->getContext();
  if (context.getGenDwarfSection() != MCOS->getCurrentSection())
    return;

  // The dwarf label's name does not have the symbol name's leading
  // underbar if any.
  StringRef Name = Symbol->getName();
  if (Name.startswith("_"))
    Name = Name.substr(1, Name.size()-1);

  // Get the dwarf file number to be used for the dwarf label.
  unsigned FileNumber = context.getGenDwarfFileNumber();

  // Finding the line number is the expensive part which is why we just don't
  // pass it in as for some symbols we won't create a dwarf label.
  int CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
  unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);

  // We create a temporary symbol for use for the AT_high_pc and AT_low_pc
  // values so that they don't have things like an ARM thumb bit from the
  // original symbol. So when used they won't get a low bit set after
  // relocation.
  MCSymbol *Label = context.CreateTempSymbol();
  MCOS->EmitLabel(Label);

  // Create and entry for the info and add it to the other entries.
  MCGenDwarfLabelEntry *Entry =
    new MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label);
  MCOS->getContext().addMCGenDwarfLabelEntry(Entry);
}

static int getDataAlignmentFactor(MCStreamer &streamer) {
  MCContext &context = streamer.getContext();
  const MCAsmInfo &asmInfo = context.getAsmInfo();
  int size = asmInfo.getCalleeSaveStackSlotSize();
  if (asmInfo.isStackGrowthDirectionUp())
    return size;
  else
    return -size;
}

static unsigned getSizeForEncoding(MCStreamer &streamer,
                                   unsigned symbolEncoding) {
  MCContext &context = streamer.getContext();
  unsigned format = symbolEncoding & 0x0f;
  switch (format) {
  default: llvm_unreachable("Unknown Encoding");
  case dwarf::DW_EH_PE_absptr:
  case dwarf::DW_EH_PE_signed:
    return context.getAsmInfo().getPointerSize();
  case dwarf::DW_EH_PE_udata2:
  case dwarf::DW_EH_PE_sdata2:
    return 2;
  case dwarf::DW_EH_PE_udata4:
  case dwarf::DW_EH_PE_sdata4:
    return 4;
  case dwarf::DW_EH_PE_udata8:
  case dwarf::DW_EH_PE_sdata8:
    return 8;
  }
}

static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
                       unsigned symbolEncoding, const char *comment = 0) {
  MCContext &context = streamer.getContext();
  const MCAsmInfo &asmInfo = context.getAsmInfo();
  const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol,
                                                symbolEncoding,
                                                streamer);
  unsigned size = getSizeForEncoding(streamer, symbolEncoding);
  if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment);
  streamer.EmitAbsValue(v, size);
}

static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
                            unsigned symbolEncoding) {
  MCContext &context = streamer.getContext();
  const MCAsmInfo &asmInfo = context.getAsmInfo();
  const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol,
                                                        symbolEncoding,
                                                        streamer);
  unsigned size = getSizeForEncoding(streamer, symbolEncoding);
  streamer.EmitValue(v, size);
}

static const MachineLocation TranslateMachineLocation(
                                                  const MCRegisterInfo &MRI,
                                                  const MachineLocation &Loc) {
  unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ?
    MachineLocation::VirtualFP :
    unsigned(MRI.getDwarfRegNum(Loc.getReg(), true));
  const MachineLocation &NewLoc = Loc.isReg() ?
    MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset());
  return NewLoc;
}

namespace {
  class FrameEmitterImpl {
    int CFAOffset;
    int CIENum;
    bool UsingCFI;
    bool IsEH;
    const MCSymbol *SectionStart;
  public:
    FrameEmitterImpl(bool usingCFI, bool isEH)
      : CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH),
        SectionStart(0) {}

    void setSectionStart(const MCSymbol *Label) { SectionStart = Label; }

    /// EmitCompactUnwind - Emit the unwind information in a compact way. If
    /// we're successful, return 'true'. Otherwise, return 'false' and it will
    /// emit the normal CIE and FDE.
    bool EmitCompactUnwind(MCStreamer &streamer,
                           const MCDwarfFrameInfo &frame);

    const MCSymbol &EmitCIE(MCStreamer &streamer,
                            const MCSymbol *personality,
                            unsigned personalityEncoding,
                            const MCSymbol *lsda,
                            bool IsSignalFrame,
                            unsigned lsdaEncoding);
    MCSymbol *EmitFDE(MCStreamer &streamer,
                      const MCSymbol &cieStart,
                      const MCDwarfFrameInfo &frame);
    void EmitCFIInstructions(MCStreamer &streamer,
                             const std::vector<MCCFIInstruction> &Instrs,
                             MCSymbol *BaseLabel);
    void EmitCFIInstruction(MCStreamer &Streamer,
                            const MCCFIInstruction &Instr);
  };

} // end anonymous namespace

static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding,
                             StringRef Prefix) {
  if (Streamer.isVerboseAsm()) {
    const char *EncStr;
    switch (Encoding) {
    default: EncStr = "<unknown encoding>"; break;
    case dwarf::DW_EH_PE_absptr: EncStr = "absptr"; break;
    case dwarf::DW_EH_PE_omit:   EncStr = "omit"; break;
    case dwarf::DW_EH_PE_pcrel:  EncStr = "pcrel"; break;
    case dwarf::DW_EH_PE_udata4: EncStr = "udata4"; break;
    case dwarf::DW_EH_PE_udata8: EncStr = "udata8"; break;
    case dwarf::DW_EH_PE_sdata4: EncStr = "sdata4"; break;
    case dwarf::DW_EH_PE_sdata8: EncStr = "sdata8"; break;
    case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
      EncStr = "pcrel udata4";
      break;
    case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
      EncStr = "pcrel sdata4";
      break;
    case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
      EncStr = "pcrel udata8";
      break;
    case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
      EncStr = "screl sdata8";
      break;
    case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4:
      EncStr = "indirect pcrel udata4";
      break;
    case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4:
      EncStr = "indirect pcrel sdata4";
      break;
    case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8:
      EncStr = "indirect pcrel udata8";
      break;
    case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8:
      EncStr = "indirect pcrel sdata8";
      break;
    }

    Streamer.AddComment(Twine(Prefix) + " = " + EncStr);
  }

  Streamer.EmitIntValue(Encoding, 1);
}

void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,
                                          const MCCFIInstruction &Instr) {
  int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
  bool VerboseAsm = Streamer.isVerboseAsm();

  switch (Instr.getOperation()) {
  case MCCFIInstruction::OpRegister: {
    unsigned Reg1 = Instr.getRegister();
    unsigned Reg2 = Instr.getRegister2();
    if (VerboseAsm) {
      Streamer.AddComment("DW_CFA_register");
      Streamer.AddComment(Twine("Reg1 ") + Twine(Reg1));
      Streamer.AddComment(Twine("Reg2 ") + Twine(Reg2));
    }
    Streamer.EmitIntValue(dwarf::DW_CFA_register, 1);
    Streamer.EmitULEB128IntValue(Reg1);
    Streamer.EmitULEB128IntValue(Reg2);
    return;
  }
  case MCCFIInstruction::OpUndefined: {
    unsigned Reg = Instr.getRegister();
    if (VerboseAsm) {
      Streamer.AddComment("DW_CFA_undefined");
      Streamer.AddComment(Twine("Reg ") + Twine(Reg));
    }
    Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1);
    Streamer.EmitULEB128IntValue(Reg);
    return;
  }
  case MCCFIInstruction::OpAdjustCfaOffset:
  case MCCFIInstruction::OpDefCfaOffset: {
    const bool IsRelative =
      Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;

    if (VerboseAsm)
      Streamer.AddComment("DW_CFA_def_cfa_offset");
    Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);

    if (IsRelative)
      CFAOffset += Instr.getOffset();
    else
      CFAOffset = -Instr.getOffset();

    if (VerboseAsm)
      Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
    Streamer.EmitULEB128IntValue(CFAOffset);

    return;
  }
  case MCCFIInstruction::OpDefCfa: {
    if (VerboseAsm)
      Streamer.AddComment("DW_CFA_def_cfa");
    Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);

    if (VerboseAsm)
      Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister()));
    Streamer.EmitULEB128IntValue(Instr.getRegister());

    CFAOffset = -Instr.getOffset();

    if (VerboseAsm)
      Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
    Streamer.EmitULEB128IntValue(CFAOffset);

    return;
  }

  case MCCFIInstruction::OpDefCfaRegister: {
    if (VerboseAsm)
      Streamer.AddComment("DW_CFA_def_cfa_register");
    Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);

    if (VerboseAsm)
      Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister()));
    Streamer.EmitULEB128IntValue(Instr.getRegister());

    return;
  }

  case MCCFIInstruction::OpOffset:
  case MCCFIInstruction::OpRelOffset: {
    const bool IsRelative =
      Instr.getOperation() == MCCFIInstruction::OpRelOffset;

    unsigned Reg = Instr.getRegister();
    int Offset = Instr.getOffset();
    if (IsRelative)
      Offset -= CFAOffset;
    Offset = Offset / dataAlignmentFactor;

    if (Offset < 0) {
      if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf");
      Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1);
      if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
      Streamer.EmitULEB128IntValue(Reg);
      if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
      Streamer.EmitSLEB128IntValue(Offset);
    } else if (Reg < 64) {
      if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") +
                                          Twine(Reg) + ")");
      Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1);
      if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
      Streamer.EmitULEB128IntValue(Offset);
    } else {
      if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended");
      Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1);
      if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
      Streamer.EmitULEB128IntValue(Reg);
      if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
      Streamer.EmitULEB128IntValue(Offset);
    }
    return;
  }
  case MCCFIInstruction::OpRememberState:
    if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state");
    Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1);
    return;
  case MCCFIInstruction::OpRestoreState:
    if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state");
    Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
    return;
  case MCCFIInstruction::OpSameValue: {
    unsigned Reg = Instr.getRegister();
    if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value");
    Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1);
    if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
    Streamer.EmitULEB128IntValue(Reg);
    return;
  }
  case MCCFIInstruction::OpRestore: {
    unsigned Reg = Instr.getRegister();
    if (VerboseAsm) {
      Streamer.AddComment("DW_CFA_restore");
      Streamer.AddComment(Twine("Reg ") + Twine(Reg));
    }
    Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
    return;
  }
  case MCCFIInstruction::OpEscape:
    if (VerboseAsm) Streamer.AddComment("Escape bytes");
    Streamer.EmitBytes(Instr.getValues());
    return;
  }
  llvm_unreachable("Unhandled case in switch");
}

/// EmitFrameMoves - Emit frame instructions to describe the layout of the
/// frame.
void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer,
                                    const std::vector<MCCFIInstruction> &Instrs,
                                           MCSymbol *BaseLabel) {
  for (unsigned i = 0, N = Instrs.size(); i < N; ++i) {
    const MCCFIInstruction &Instr = Instrs[i];
    MCSymbol *Label = Instr.getLabel();
    // Throw out move if the label is invalid.
    if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.

    // Advance row if new location.
    if (BaseLabel && Label) {
      MCSymbol *ThisSym = Label;
      if (ThisSym != BaseLabel) {
        if (streamer.isVerboseAsm()) streamer.AddComment("DW_CFA_advance_loc4");
        streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
        BaseLabel = ThisSym;
      }
    }

    EmitCFIInstruction(streamer, Instr);
  }
}

/// EmitCompactUnwind - Emit the unwind information in a compact way. If we're
/// successful, return 'true'. Otherwise, return 'false' and it will emit the
/// normal CIE and FDE.
bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
                                         const MCDwarfFrameInfo &Frame) {
  MCContext &Context = Streamer.getContext();
  const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
  bool VerboseAsm = Streamer.isVerboseAsm();

  // range-start range-length  compact-unwind-enc personality-func   lsda
  //  _foo       LfooEnd-_foo  0x00000023          0                 0
  //  _bar       LbarEnd-_bar  0x00000025         __gxx_personality  except_tab1
  //
  //   .section __LD,__compact_unwind,regular,debug
  //
  //   # compact unwind for _foo
  //   .quad _foo
  //   .set L1,LfooEnd-_foo
  //   .long L1
  //   .long 0x01010001
  //   .quad 0
  //   .quad 0
  //
  //   # compact unwind for _bar
  //   .quad _bar
  //   .set L2,LbarEnd-_bar
  //   .long L2
  //   .long 0x01020011
  //   .quad __gxx_personality
  //   .quad except_tab1

  uint32_t Encoding = Frame.CompactUnwindEncoding;
  if (!Encoding) return false;

  // The encoding needs to know we have an LSDA.
  if (Frame.Lsda)
    Encoding |= 0x40000000;

  Streamer.SwitchSection(MOFI->getCompactUnwindSection());

  // Range Start
  unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI);
  unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
  if (VerboseAsm) Streamer.AddComment("Range Start");
  Streamer.EmitSymbolValue(Frame.Function, Size);

  // Range Length
  const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin,
                                              *Frame.End, 0);
  if (VerboseAsm) Streamer.AddComment("Range Length");
  Streamer.EmitAbsValue(Range, 4);

  // Compact Encoding
  Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
  if (VerboseAsm) Streamer.AddComment("Compact Unwind Encoding: 0x" +
                                      Twine::utohexstr(Encoding));
  Streamer.EmitIntValue(Encoding, Size);


  // Personality Function
  Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);
  if (VerboseAsm) Streamer.AddComment("Personality Function");
  if (Frame.Personality)
    Streamer.EmitSymbolValue(Frame.Personality, Size);
  else
    Streamer.EmitIntValue(0, Size); // No personality fn

  // LSDA
  Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);
  if (VerboseAsm) Streamer.AddComment("LSDA");
  if (Frame.Lsda)
    Streamer.EmitSymbolValue(Frame.Lsda, Size);
  else
    Streamer.EmitIntValue(0, Size); // No LSDA

  return true;
}

const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
                                          const MCSymbol *personality,
                                          unsigned personalityEncoding,
                                          const MCSymbol *lsda,
                                          bool IsSignalFrame,
                                          unsigned lsdaEncoding) {
  MCContext &context = streamer.getContext();
  const MCRegisterInfo &MRI = context.getRegisterInfo();
  const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
  bool verboseAsm = streamer.isVerboseAsm();

  MCSymbol *sectionStart;
  if (MOFI->isFunctionEHFrameSymbolPrivate() || !IsEH)
    sectionStart = context.CreateTempSymbol();
  else
    sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum));

  streamer.EmitLabel(sectionStart);
  CIENum++;

  MCSymbol *sectionEnd = context.CreateTempSymbol();

  // Length
  const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart,
                                               *sectionEnd, 4);
  if (verboseAsm) streamer.AddComment("CIE Length");
  streamer.EmitAbsValue(Length, 4);

  // CIE ID
  unsigned CIE_ID = IsEH ? 0 : -1;
  if (verboseAsm) streamer.AddComment("CIE ID Tag");
  streamer.EmitIntValue(CIE_ID, 4);

  // Version
  if (verboseAsm) streamer.AddComment("DW_CIE_VERSION");
  streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1);

  // Augmentation String
  SmallString<8> Augmentation;
  if (IsEH) {
    if (verboseAsm) streamer.AddComment("CIE Augmentation");
    Augmentation += "z";
    if (personality)
      Augmentation += "P";
    if (lsda)
      Augmentation += "L";
    Augmentation += "R";
    if (IsSignalFrame)
      Augmentation += "S";
    streamer.EmitBytes(Augmentation.str());
  }
  streamer.EmitIntValue(0, 1);

  // Code Alignment Factor
  if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor");
  streamer.EmitULEB128IntValue(1);

  // Data Alignment Factor
  if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor");
  streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer));

  // Return Address Register
  if (verboseAsm) streamer.AddComment("CIE Return Address Column");
  streamer.EmitULEB128IntValue(MRI.getDwarfRegNum(MRI.getRARegister(), true));

  // Augmentation Data Length (optional)

  unsigned augmentationLength = 0;
  if (IsEH) {
    if (personality) {
      // Personality Encoding
      augmentationLength += 1;
      // Personality
      augmentationLength += getSizeForEncoding(streamer, personalityEncoding);
    }
    if (lsda)
      augmentationLength += 1;
    // Encoding of the FDE pointers
    augmentationLength += 1;

    if (verboseAsm) streamer.AddComment("Augmentation Size");
    streamer.EmitULEB128IntValue(augmentationLength);

    // Augmentation Data (optional)
    if (personality) {
      // Personality Encoding
      EmitEncodingByte(streamer, personalityEncoding,
                       "Personality Encoding");
      // Personality
      if (verboseAsm) streamer.AddComment("Personality");
      EmitPersonality(streamer, *personality, personalityEncoding);
    }

    if (lsda)
      EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding");

    // Encoding of the FDE pointers
    EmitEncodingByte(streamer, MOFI->getFDEEncoding(UsingCFI),
                     "FDE Encoding");
  }

  // Initial Instructions

  const MCAsmInfo &MAI = context.getAsmInfo();
  const std::vector<MachineMove> &Moves = MAI.getInitialFrameState();
  std::vector<MCCFIInstruction> Instructions;

  for (int i = 0, n = Moves.size(); i != n; ++i) {
    MCSymbol *Label = Moves[i].getLabel();
    const MachineLocation &Dst =
      TranslateMachineLocation(MRI, Moves[i].getDestination());
    const MachineLocation &Src =
      TranslateMachineLocation(MRI, Moves[i].getSource());

    if (Dst.isReg()) {
      assert(Dst.getReg() == MachineLocation::VirtualFP);
      assert(!Src.isReg());
      MCCFIInstruction Inst =
        MCCFIInstruction::createDefCfa(Label, Src.getReg(), -Src.getOffset());
      Instructions.push_back(Inst);
    } else {
      assert(Src.isReg());
      unsigned Reg = Src.getReg();
      int Offset = Dst.getOffset();
      MCCFIInstruction Inst =
        MCCFIInstruction::createOffset(Label, Reg, Offset);
      Instructions.push_back(Inst);
    }
  }

  EmitCFIInstructions(streamer, Instructions, NULL);

  // Padding
  streamer.EmitValueToAlignment(IsEH
                                ? 4 : context.getAsmInfo().getPointerSize());

  streamer.EmitLabel(sectionEnd);
  return *sectionStart;
}

MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,
                                    const MCSymbol &cieStart,
                                    const MCDwarfFrameInfo &frame) {
  MCContext &context = streamer.getContext();
  MCSymbol *fdeStart = context.CreateTempSymbol();
  MCSymbol *fdeEnd = context.CreateTempSymbol();
  const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
  bool verboseAsm = streamer.isVerboseAsm();

  if (IsEH && frame.Function && !MOFI->isFunctionEHFrameSymbolPrivate()) {
    MCSymbol *EHSym =
      context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh"));
    streamer.EmitEHSymAttributes(frame.Function, EHSym);
    streamer.EmitLabel(EHSym);
  }

  // Length
  const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0);
  if (verboseAsm) streamer.AddComment("FDE Length");
  streamer.EmitAbsValue(Length, 4);

  streamer.EmitLabel(fdeStart);

  // CIE Pointer
  const MCAsmInfo &asmInfo = context.getAsmInfo();
  if (IsEH) {
    const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart,
                                                 0);
    if (verboseAsm) streamer.AddComment("FDE CIE Offset");
    streamer.EmitAbsValue(offset, 4);
  } else if (!asmInfo.doesDwarfUseRelocationsAcrossSections()) {
    const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart,
                                                 cieStart, 0);
    streamer.EmitAbsValue(offset, 4);
  } else {
    streamer.EmitSymbolValue(&cieStart, 4);
  }

  // PC Begin
  unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding(UsingCFI)
                             : (unsigned)dwarf::DW_EH_PE_absptr;
  unsigned PCSize = getSizeForEncoding(streamer, PCEncoding);
  EmitSymbol(streamer, *frame.Begin, PCEncoding, "FDE initial location");

  // PC Range
  const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin,
                                              *frame.End, 0);
  if (verboseAsm) streamer.AddComment("FDE address range");
  streamer.EmitAbsValue(Range, PCSize);

  if (IsEH) {
    // Augmentation Data Length
    unsigned augmentationLength = 0;

    if (frame.Lsda)
      augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding);

    if (verboseAsm) streamer.AddComment("Augmentation size");
    streamer.EmitULEB128IntValue(augmentationLength);

    // Augmentation Data
    if (frame.Lsda)
      EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding,
                 "Language Specific Data Area");
  }

  // Call Frame Instructions

  EmitCFIInstructions(streamer, frame.Instructions, frame.Begin);

  // Padding
  streamer.EmitValueToAlignment(PCSize);

  return fdeEnd;
}

namespace {
  struct CIEKey {
    static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false); }
    static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false); }

    CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_,
           unsigned LsdaEncoding_, bool IsSignalFrame_) :
      Personality(Personality_), PersonalityEncoding(PersonalityEncoding_),
      LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_) {
    }
    const MCSymbol* Personality;
    unsigned PersonalityEncoding;
    unsigned LsdaEncoding;
    bool IsSignalFrame;
  };
}

namespace llvm {
  template <>
  struct DenseMapInfo<CIEKey> {
    static CIEKey getEmptyKey() {
      return CIEKey::getEmptyKey();
    }
    static CIEKey getTombstoneKey() {
      return CIEKey::getTombstoneKey();
    }
    static unsigned getHashValue(const CIEKey &Key) {
      return static_cast<unsigned>(hash_combine(Key.Personality,
                                                Key.PersonalityEncoding,
                                                Key.LsdaEncoding,
                                                Key.IsSignalFrame));
    }
    static bool isEqual(const CIEKey &LHS,
                        const CIEKey &RHS) {
      return LHS.Personality == RHS.Personality &&
        LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
        LHS.LsdaEncoding == RHS.LsdaEncoding &&
        LHS.IsSignalFrame == RHS.IsSignalFrame;
    }
  };
}

void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer,
                               bool UsingCFI,
                               bool IsEH) {
  MCContext &Context = Streamer.getContext();
  MCObjectFileInfo *MOFI =
    const_cast<MCObjectFileInfo*>(Context.getObjectFileInfo());
  FrameEmitterImpl Emitter(UsingCFI, IsEH);
  ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos();

  // Emit the compact unwind info if available.
  if (IsEH && MOFI->getCompactUnwindSection())
    for (unsigned i = 0, n = Streamer.getNumFrameInfos(); i < n; ++i) {
      const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i);
      if (Frame.CompactUnwindEncoding)
        Emitter.EmitCompactUnwind(Streamer, Frame);
    }

  const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() :
                                    *MOFI->getDwarfFrameSection();
  Streamer.SwitchSection(&Section);
  MCSymbol *SectionStart = Context.CreateTempSymbol();
  Streamer.EmitLabel(SectionStart);
  Emitter.setSectionStart(SectionStart);

  MCSymbol *FDEEnd = NULL;
  DenseMap<CIEKey, const MCSymbol*> CIEStarts;

  const MCSymbol *DummyDebugKey = NULL;
  for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
    const MCDwarfFrameInfo &Frame = FrameArray[i];
    CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
               Frame.LsdaEncoding, Frame.IsSignalFrame);
    const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
    if (!CIEStart)
      CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality,
                                  Frame.PersonalityEncoding, Frame.Lsda,
                                  Frame.IsSignalFrame,
                                  Frame.LsdaEncoding);

    FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame);

    if (i != n - 1)
      Streamer.EmitLabel(FDEEnd);
  }

  Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize());
  if (FDEEnd)
    Streamer.EmitLabel(FDEEnd);
}

void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer,
                                         uint64_t AddrDelta) {
  SmallString<256> Tmp;
  raw_svector_ostream OS(Tmp);
  MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS);
  Streamer.EmitBytes(OS.str());
}

void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta,
                                           raw_ostream &OS) {
  // FIXME: Assumes the code alignment factor is 1.
  if (AddrDelta == 0) {
  } else if (isUIntN(6, AddrDelta)) {
    uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
    OS << Opcode;
  } else if (isUInt<8>(AddrDelta)) {
    OS << uint8_t(dwarf::DW_CFA_advance_loc1);
    OS << uint8_t(AddrDelta);
  } else if (isUInt<16>(AddrDelta)) {
    // FIXME: check what is the correct behavior on a big endian machine.
    OS << uint8_t(dwarf::DW_CFA_advance_loc2);
    OS << uint8_t( AddrDelta       & 0xff);
    OS << uint8_t((AddrDelta >> 8) & 0xff);
  } else {
    // FIXME: check what is the correct behavior on a big endian machine.
    assert(isUInt<32>(AddrDelta));
    OS << uint8_t(dwarf::DW_CFA_advance_loc4);
    OS << uint8_t( AddrDelta        & 0xff);
    OS << uint8_t((AddrDelta >> 8)  & 0xff);
    OS << uint8_t((AddrDelta >> 16) & 0xff);
    OS << uint8_t((AddrDelta >> 24) & 0xff);

  }
}
