LLVM API Documentation

MCDwarf.cpp
Go to the documentation of this file.
00001 //===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "llvm/MC/MCDwarf.h"
00011 #include "llvm/ADT/Hashing.h"
00012 #include "llvm/ADT/SmallString.h"
00013 #include "llvm/ADT/Twine.h"
00014 #include "llvm/Config/config.h"
00015 #include "llvm/MC/MCAsmInfo.h"
00016 #include "llvm/MC/MCContext.h"
00017 #include "llvm/MC/MCExpr.h"
00018 #include "llvm/MC/MCObjectFileInfo.h"
00019 #include "llvm/MC/MCObjectWriter.h"
00020 #include "llvm/MC/MCRegisterInfo.h"
00021 #include "llvm/MC/MCStreamer.h"
00022 #include "llvm/MC/MCSymbol.h"
00023 #include "llvm/Support/Debug.h"
00024 #include "llvm/Support/ErrorHandling.h"
00025 #include "llvm/Support/LEB128.h"
00026 #include "llvm/Support/Path.h"
00027 #include "llvm/Support/SourceMgr.h"
00028 #include "llvm/Support/raw_ostream.h"
00029 using namespace llvm;
00030 
00031 // Given a special op, return the address skip amount (in units of
00032 // DWARF2_LINE_MIN_INSN_LENGTH.
00033 #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)
00034 
00035 // The maximum address skip amount that can be encoded with a special op.
00036 #define MAX_SPECIAL_ADDR_DELTA         SPECIAL_ADDR(255)
00037 
00038 // First special line opcode - leave room for the standard opcodes.
00039 // Note: If you want to change this, you'll have to update the
00040 // "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit().
00041 #define DWARF2_LINE_OPCODE_BASE         13
00042 
00043 // Minimum line offset in a special line info. opcode.  This value
00044 // was chosen to give a reasonable range of values.
00045 #define DWARF2_LINE_BASE                -5
00046 
00047 // Range of line offsets in a special line info. opcode.
00048 #define DWARF2_LINE_RANGE               14
00049 
00050 // Define the architecture-dependent minimum instruction length (in bytes).
00051 // This value should be rather too small than too big.
00052 #define DWARF2_LINE_MIN_INSN_LENGTH     1
00053 
00054 // Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting,
00055 // this routine is a nop and will be optimized away.
00056 static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) {
00057   if (DWARF2_LINE_MIN_INSN_LENGTH == 1)
00058     return AddrDelta;
00059   if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) {
00060     // TODO: report this error, but really only once.
00061     ;
00062   }
00063   return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH;
00064 }
00065 
00066 //
00067 // This is called when an instruction is assembled into the specified section
00068 // and if there is information from the last .loc directive that has yet to have
00069 // a line entry made for it is made.
00070 //
00071 void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) {
00072   if (!MCOS->getContext().getDwarfLocSeen())
00073     return;
00074 
00075   // Create a symbol at in the current section for use in the line entry.
00076   MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol();
00077   // Set the value of the symbol to use for the MCLineEntry.
00078   MCOS->EmitLabel(LineSym);
00079 
00080   // Get the current .loc info saved in the context.
00081   const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();
00082 
00083   // Create a (local) line entry with the symbol and the current .loc info.
00084   MCLineEntry LineEntry(LineSym, DwarfLoc);
00085 
00086   // clear DwarfLocSeen saying the current .loc info is now used.
00087   MCOS->getContext().ClearDwarfLocSeen();
00088 
00089   // Get the MCLineSection for this section, if one does not exist for this
00090   // section create it.
00091   const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
00092     MCOS->getContext().getMCLineSections();
00093   MCLineSection *LineSection = MCLineSections.lookup(Section);
00094   if (!LineSection) {
00095     // Create a new MCLineSection.  This will be deleted after the dwarf line
00096     // table is created using it by iterating through the MCLineSections
00097     // DenseMap.
00098     LineSection = new MCLineSection;
00099     // Save a pointer to the new LineSection into the MCLineSections DenseMap.
00100     MCOS->getContext().addMCLineSection(Section, LineSection);
00101   }
00102 
00103   // Add the line entry to this section's entries.
00104   LineSection->addLineEntry(LineEntry,
00105                             MCOS->getContext().getDwarfCompileUnitID());
00106 }
00107 
00108 //
00109 // This helper routine returns an expression of End - Start + IntVal .
00110 //
00111 static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
00112                                                   const MCSymbol &Start,
00113                                                   const MCSymbol &End,
00114                                                   int IntVal) {
00115   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
00116   const MCExpr *Res =
00117     MCSymbolRefExpr::Create(&End, Variant, MCOS.getContext());
00118   const MCExpr *RHS =
00119     MCSymbolRefExpr::Create(&Start, Variant, MCOS.getContext());
00120   const MCExpr *Res1 =
00121     MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext());
00122   const MCExpr *Res2 =
00123     MCConstantExpr::Create(IntVal, MCOS.getContext());
00124   const MCExpr *Res3 =
00125     MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext());
00126   return Res3;
00127 }
00128 
00129 //
00130 // This emits the Dwarf line table for the specified section from the entries
00131 // in the LineSection.
00132 //
00133 static inline void EmitDwarfLineTable(MCStreamer *MCOS,
00134                                       const MCSection *Section,
00135                                       const MCLineSection *LineSection,
00136                                       unsigned CUID) {
00137   // This LineSection does not contain any LineEntry for the given Compile Unit.
00138   if (!LineSection->containEntriesForID(CUID))
00139     return;
00140 
00141   unsigned FileNum = 1;
00142   unsigned LastLine = 1;
00143   unsigned Column = 0;
00144   unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
00145   unsigned Isa = 0;
00146   MCSymbol *LastLabel = NULL;
00147 
00148   // Loop through each MCLineEntry and encode the dwarf line number table.
00149   for (MCLineSection::const_iterator
00150          it = LineSection->getMCLineEntries(CUID).begin(),
00151          ie = LineSection->getMCLineEntries(CUID).end(); it != ie; ++it) {
00152 
00153     if (FileNum != it->getFileNum()) {
00154       FileNum = it->getFileNum();
00155       MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
00156       MCOS->EmitULEB128IntValue(FileNum);
00157     }
00158     if (Column != it->getColumn()) {
00159       Column = it->getColumn();
00160       MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
00161       MCOS->EmitULEB128IntValue(Column);
00162     }
00163     if (Isa != it->getIsa()) {
00164       Isa = it->getIsa();
00165       MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
00166       MCOS->EmitULEB128IntValue(Isa);
00167     }
00168     if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
00169       Flags = it->getFlags();
00170       MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1);
00171     }
00172     if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK)
00173       MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1);
00174     if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END)
00175       MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
00176     if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
00177       MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
00178 
00179     int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine;
00180     MCSymbol *Label = it->getLabel();
00181 
00182     // At this point we want to emit/create the sequence to encode the delta in
00183     // line numbers and the increment of the address from the previous Label
00184     // and the current Label.
00185     const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo();
00186     MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
00187                                    asmInfo.getPointerSize());
00188 
00189     LastLine = it->getLine();
00190     LastLabel = Label;
00191   }
00192 
00193   // Emit a DW_LNE_end_sequence for the end of the section.
00194   // Using the pointer Section create a temporary label at the end of the
00195   // section and use that and the LastLabel to compute the address delta
00196   // and use INT64_MAX as the line delta which is the signal that this is
00197   // actually a DW_LNE_end_sequence.
00198 
00199   // Switch to the section to be able to create a symbol at its end.
00200   // TODO: keep track of the last subsection so that this symbol appears in the
00201   // correct place.
00202   MCOS->SwitchSection(Section);
00203 
00204   MCContext &context = MCOS->getContext();
00205   // Create a symbol at the end of the section.
00206   MCSymbol *SectionEnd = context.CreateTempSymbol();
00207   // Set the value of the symbol, as we are at the end of the section.
00208   MCOS->EmitLabel(SectionEnd);
00209 
00210   // Switch back the dwarf line section.
00211   MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
00212 
00213   const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo();
00214   MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
00215                                  asmInfo.getPointerSize());
00216 }
00217 
00218 //
00219 // This emits the Dwarf file and the line tables.
00220 //
00221 const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) {
00222   MCContext &context = MCOS->getContext();
00223   // Switch to the section where the table will be emitted into.
00224   MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection());
00225 
00226   const DenseMap<unsigned, MCSymbol *> &MCLineTableSymbols =
00227     MCOS->getContext().getMCLineTableSymbols();
00228   // CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does
00229   // not exist, CUID will be 0 and MCLineTableSymbols will be empty.
00230   // Handle Compile Unit 0, the line table start symbol is the section symbol.
00231   const MCSymbol *LineStartSym = EmitCU(MCOS, 0);
00232   // Handle the rest of the Compile Units.
00233   for (unsigned Is = 1, Ie = MCLineTableSymbols.size(); Is < Ie; Is++)
00234     EmitCU(MCOS, Is);
00235 
00236   // Now delete the MCLineSections that were created in MCLineEntry::Make()
00237   // and used to emit the line table.
00238   const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
00239     MCOS->getContext().getMCLineSections();
00240   for (DenseMap<const MCSection *, MCLineSection *>::const_iterator it =
00241        MCLineSections.begin(), ie = MCLineSections.end(); it != ie;
00242        ++it)
00243     delete it->second;
00244 
00245   return LineStartSym;
00246 }
00247 
00248 const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) {
00249   MCContext &context = MCOS->getContext();
00250 
00251   // Create a symbol at the beginning of the line table.
00252   MCSymbol *LineStartSym = MCOS->getContext().getMCLineTableSymbol(CUID);
00253   if (!LineStartSym)
00254     LineStartSym = context.CreateTempSymbol();
00255   // Set the value of the symbol, as we are at the start of the line table.
00256   MCOS->EmitLabel(LineStartSym);
00257 
00258   // Create a symbol for the end of the section (to be set when we get there).
00259   MCSymbol *LineEndSym = context.CreateTempSymbol();
00260 
00261   // The first 4 bytes is the total length of the information for this
00262   // compilation unit (not including these 4 bytes for the length).
00263   MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym,4),
00264                      4);
00265 
00266   // Next 2 bytes is the Version, which is Dwarf 2.
00267   MCOS->EmitIntValue(2, 2);
00268 
00269   // Create a symbol for the end of the prologue (to be set when we get there).
00270   MCSymbol *ProEndSym = context.CreateTempSymbol(); // Lprologue_end
00271 
00272   // Length of the prologue, is the next 4 bytes.  Which is the start of the
00273   // section to the end of the prologue.  Not including the 4 bytes for the
00274   // total length, the 2 bytes for the version, and these 4 bytes for the
00275   // length of the prologue.
00276   MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym,
00277                                            (4 + 2 + 4)), 4, 0);
00278 
00279   // Parameters of the state machine, are next.
00280   MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1);
00281   MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1);
00282   MCOS->EmitIntValue(DWARF2_LINE_BASE, 1);
00283   MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1);
00284   MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1);
00285 
00286   // Standard opcode lengths
00287   MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy
00288   MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc
00289   MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line
00290   MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file
00291   MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column
00292   MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt
00293   MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block
00294   MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc
00295   MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc
00296   MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end
00297   MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin
00298   MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa
00299 
00300   // Put out the directory and file tables.
00301 
00302   // First the directory table.
00303   const SmallVectorImpl<StringRef> &MCDwarfDirs =
00304     context.getMCDwarfDirs(CUID);
00305   for (unsigned i = 0; i < MCDwarfDirs.size(); i++) {
00306     MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName
00307     MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
00308   }
00309   MCOS->EmitIntValue(0, 1); // Terminate the directory list
00310 
00311   // Second the file table.
00312   const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
00313     MCOS->getContext().getMCDwarfFiles(CUID);
00314   for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
00315     MCOS->EmitBytes(MCDwarfFiles[i]->getName()); // FileName
00316     MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string
00317     // the Directory num
00318     MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex());
00319     MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
00320     MCOS->EmitIntValue(0, 1); // filesize (always 0)
00321   }
00322   MCOS->EmitIntValue(0, 1); // Terminate the file list
00323 
00324   // This is the end of the prologue, so set the value of the symbol at the
00325   // end of the prologue (that was used in a previous expression).
00326   MCOS->EmitLabel(ProEndSym);
00327 
00328   // Put out the line tables.
00329   const DenseMap<const MCSection *, MCLineSection *> &MCLineSections =
00330     MCOS->getContext().getMCLineSections();
00331   const std::vector<const MCSection *> &MCLineSectionOrder =
00332     MCOS->getContext().getMCLineSectionOrder();
00333   for (std::vector<const MCSection*>::const_iterator it =
00334          MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie;
00335        ++it) {
00336     const MCSection *Sec = *it;
00337     const MCLineSection *Line = MCLineSections.lookup(Sec);
00338     EmitDwarfLineTable(MCOS, Sec, Line, CUID);
00339   }
00340 
00341   if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines()
00342       && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) {
00343     // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures
00344     // it requires:
00345     // total_length >= prologue_length + 10
00346     // We are 4 bytes short, since we have total_length = 51 and
00347     // prologue_length = 45
00348 
00349     // The regular end_sequence should be sufficient.
00350     MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0);
00351   }
00352 
00353   // This is the end of the section, so set the value of the symbol at the end
00354   // of this section (that was used in a previous expression).
00355   MCOS->EmitLabel(LineEndSym);
00356 
00357   return LineStartSym;
00358 }
00359 
00360 /// Utility function to write the encoding to an object writer.
00361 void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta,
00362                             uint64_t AddrDelta) {
00363   SmallString<256> Tmp;
00364   raw_svector_ostream OS(Tmp);
00365   MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
00366   OW->WriteBytes(OS.str());
00367 }
00368 
00369 /// Utility function to emit the encoding to a streamer.
00370 void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta,
00371                            uint64_t AddrDelta) {
00372   SmallString<256> Tmp;
00373   raw_svector_ostream OS(Tmp);
00374   MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS);
00375   MCOS->EmitBytes(OS.str());
00376 }
00377 
00378 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
00379 void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta,
00380                              raw_ostream &OS) {
00381   uint64_t Temp, Opcode;
00382   bool NeedCopy = false;
00383 
00384   // Scale the address delta by the minimum instruction length.
00385   AddrDelta = ScaleAddrDelta(AddrDelta);
00386 
00387   // A LineDelta of INT64_MAX is a signal that this is actually a
00388   // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the
00389   // end_sequence to emit the matrix entry.
00390   if (LineDelta == INT64_MAX) {
00391     if (AddrDelta == MAX_SPECIAL_ADDR_DELTA)
00392       OS << char(dwarf::DW_LNS_const_add_pc);
00393     else {
00394       OS << char(dwarf::DW_LNS_advance_pc);
00395       encodeULEB128(AddrDelta, OS);
00396     }
00397     OS << char(dwarf::DW_LNS_extended_op);
00398     OS << char(1);
00399     OS << char(dwarf::DW_LNE_end_sequence);
00400     return;
00401   }
00402 
00403   // Bias the line delta by the base.
00404   Temp = LineDelta - DWARF2_LINE_BASE;
00405 
00406   // If the line increment is out of range of a special opcode, we must encode
00407   // it with DW_LNS_advance_line.
00408   if (Temp >= DWARF2_LINE_RANGE) {
00409     OS << char(dwarf::DW_LNS_advance_line);
00410     encodeSLEB128(LineDelta, OS);
00411 
00412     LineDelta = 0;
00413     Temp = 0 - DWARF2_LINE_BASE;
00414     NeedCopy = true;
00415   }
00416 
00417   // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode.
00418   if (LineDelta == 0 && AddrDelta == 0) {
00419     OS << char(dwarf::DW_LNS_copy);
00420     return;
00421   }
00422 
00423   // Bias the opcode by the special opcode base.
00424   Temp += DWARF2_LINE_OPCODE_BASE;
00425 
00426   // Avoid overflow when addr_delta is large.
00427   if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) {
00428     // Try using a special opcode.
00429     Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE;
00430     if (Opcode <= 255) {
00431       OS << char(Opcode);
00432       return;
00433     }
00434 
00435     // Try using DW_LNS_const_add_pc followed by special op.
00436     Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
00437     if (Opcode <= 255) {
00438       OS << char(dwarf::DW_LNS_const_add_pc);
00439       OS << char(Opcode);
00440       return;
00441     }
00442   }
00443 
00444   // Otherwise use DW_LNS_advance_pc.
00445   OS << char(dwarf::DW_LNS_advance_pc);
00446   encodeULEB128(AddrDelta, OS);
00447 
00448   if (NeedCopy)
00449     OS << char(dwarf::DW_LNS_copy);
00450   else
00451     OS << char(Temp);
00452 }
00453 
00454 void MCDwarfFile::print(raw_ostream &OS) const {
00455   OS << '"' << getName() << '"';
00456 }
00457 
00458 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
00459 void MCDwarfFile::dump() const {
00460   print(dbgs());
00461 }
00462 #endif
00463 
00464 // Utility function to write a tuple for .debug_abbrev.
00465 static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
00466   MCOS->EmitULEB128IntValue(Name);
00467   MCOS->EmitULEB128IntValue(Form);
00468 }
00469 
00470 // When generating dwarf for assembly source files this emits
00471 // the data for .debug_abbrev section which contains three DIEs.
00472 static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
00473   MCContext &context = MCOS->getContext();
00474   MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
00475 
00476   // DW_TAG_compile_unit DIE abbrev (1).
00477   MCOS->EmitULEB128IntValue(1);
00478   MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
00479   MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
00480   EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4);
00481   EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
00482   EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
00483   EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
00484   EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
00485   StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
00486   if (!DwarfDebugFlags.empty())
00487     EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
00488   EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
00489   EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
00490   EmitAbbrev(MCOS, 0, 0);
00491 
00492   // DW_TAG_label DIE abbrev (2).
00493   MCOS->EmitULEB128IntValue(2);
00494   MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label);
00495   MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
00496   EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
00497   EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
00498   EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
00499   EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
00500   EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag);
00501   EmitAbbrev(MCOS, 0, 0);
00502 
00503   // DW_TAG_unspecified_parameters DIE abbrev (3).
00504   MCOS->EmitULEB128IntValue(3);
00505   MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters);
00506   MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1);
00507   EmitAbbrev(MCOS, 0, 0);
00508 
00509   // Terminate the abbreviations for this compilation unit.
00510   MCOS->EmitIntValue(0, 1);
00511 }
00512 
00513 // When generating dwarf for assembly source files this emits the data for
00514 // .debug_aranges section.  Which contains a header and a table of pairs of
00515 // PointerSize'ed values for the address and size of section(s) with line table
00516 // entries (just the default .text in our case) and a terminating pair of zeros.
00517 static void EmitGenDwarfAranges(MCStreamer *MCOS,
00518                                 const MCSymbol *InfoSectionSymbol) {
00519   MCContext &context = MCOS->getContext();
00520 
00521   // Create a symbol at the end of the section that we are creating the dwarf
00522   // debugging info to use later in here as part of the expression to calculate
00523   // the size of the section for the table.
00524   MCOS->SwitchSection(context.getGenDwarfSection());
00525   MCSymbol *SectionEndSym = context.CreateTempSymbol();
00526   MCOS->EmitLabel(SectionEndSym);
00527   context.setGenDwarfSectionEndSym(SectionEndSym);
00528 
00529   MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
00530 
00531   // This will be the length of the .debug_aranges section, first account for
00532   // the size of each item in the header (see below where we emit these items).
00533   int Length = 4 + 2 + 4 + 1 + 1;
00534 
00535   // Figure the padding after the header before the table of address and size
00536   // pairs who's values are PointerSize'ed.
00537   const MCAsmInfo &asmInfo = context.getAsmInfo();
00538   int AddrSize = asmInfo.getPointerSize();
00539   int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
00540   if (Pad == 2 * AddrSize)
00541     Pad = 0;
00542   Length += Pad;
00543 
00544   // Add the size of the pair of PointerSize'ed values for the address and size
00545   // of the one default .text section we have in the table.
00546   Length += 2 * AddrSize;
00547   // And the pair of terminating zeros.
00548   Length += 2 * AddrSize;
00549 
00550 
00551   // Emit the header for this section.
00552   // The 4 byte length not including the 4 byte value for the length.
00553   MCOS->EmitIntValue(Length - 4, 4);
00554   // The 2 byte version, which is 2.
00555   MCOS->EmitIntValue(2, 2);
00556   // The 4 byte offset to the compile unit in the .debug_info from the start
00557   // of the .debug_info.
00558   if (InfoSectionSymbol)
00559     MCOS->EmitSymbolValue(InfoSectionSymbol, 4);
00560   else
00561     MCOS->EmitIntValue(0, 4);
00562   // The 1 byte size of an address.
00563   MCOS->EmitIntValue(AddrSize, 1);
00564   // The 1 byte size of a segment descriptor, we use a value of zero.
00565   MCOS->EmitIntValue(0, 1);
00566   // Align the header with the padding if needed, before we put out the table.
00567   for(int i = 0; i < Pad; i++)
00568     MCOS->EmitIntValue(0, 1);
00569 
00570   // Now emit the table of pairs of PointerSize'ed values for the section(s)
00571   // address and size, in our case just the one default .text section.
00572   const MCExpr *Addr = MCSymbolRefExpr::Create(
00573     context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context);
00574   const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
00575     *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0);
00576   MCOS->EmitAbsValue(Addr, AddrSize);
00577   MCOS->EmitAbsValue(Size, AddrSize);
00578 
00579   // And finally the pair of terminating zeros.
00580   MCOS->EmitIntValue(0, AddrSize);
00581   MCOS->EmitIntValue(0, AddrSize);
00582 }
00583 
00584 // When generating dwarf for assembly source files this emits the data for
00585 // .debug_info section which contains three parts.  The header, the compile_unit
00586 // DIE and a list of label DIEs.
00587 static void EmitGenDwarfInfo(MCStreamer *MCOS,
00588                              const MCSymbol *AbbrevSectionSymbol,
00589                              const MCSymbol *LineSectionSymbol) {
00590   MCContext &context = MCOS->getContext();
00591 
00592   MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
00593 
00594   // Create a symbol at the start and end of this section used in here for the
00595   // expression to calculate the length in the header.
00596   MCSymbol *InfoStart = context.CreateTempSymbol();
00597   MCOS->EmitLabel(InfoStart);
00598   MCSymbol *InfoEnd = context.CreateTempSymbol();
00599 
00600   // First part: the header.
00601 
00602   // The 4 byte total length of the information for this compilation unit, not
00603   // including these 4 bytes.
00604   const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4);
00605   MCOS->EmitAbsValue(Length, 4);
00606 
00607   // The 2 byte DWARF version, which is 2.
00608   MCOS->EmitIntValue(2, 2);
00609 
00610   // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev,
00611   // it is at the start of that section so this is zero.
00612   if (AbbrevSectionSymbol) {
00613     MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4);
00614   } else {
00615     MCOS->EmitIntValue(0, 4);
00616   }
00617 
00618   const MCAsmInfo &asmInfo = context.getAsmInfo();
00619   int AddrSize = asmInfo.getPointerSize();
00620   // The 1 byte size of an address.
00621   MCOS->EmitIntValue(AddrSize, 1);
00622 
00623   // Second part: the compile_unit DIE.
00624 
00625   // The DW_TAG_compile_unit DIE abbrev (1).
00626   MCOS->EmitULEB128IntValue(1);
00627 
00628   // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section,
00629   // which is at the start of that section so this is zero.
00630   if (LineSectionSymbol) {
00631     MCOS->EmitSymbolValue(LineSectionSymbol, 4);
00632   } else {
00633     MCOS->EmitIntValue(0, 4);
00634   }
00635 
00636   // AT_low_pc, the first address of the default .text section.
00637   const MCExpr *Start = MCSymbolRefExpr::Create(
00638     context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context);
00639   MCOS->EmitAbsValue(Start, AddrSize);
00640 
00641   // AT_high_pc, the last address of the default .text section.
00642   const MCExpr *End = MCSymbolRefExpr::Create(
00643     context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context);
00644   MCOS->EmitAbsValue(End, AddrSize);
00645 
00646   // AT_name, the name of the source file.  Reconstruct from the first directory
00647   // and file table entries.
00648   const SmallVectorImpl<StringRef> &MCDwarfDirs =
00649     context.getMCDwarfDirs();
00650   if (MCDwarfDirs.size() > 0) {
00651     MCOS->EmitBytes(MCDwarfDirs[0]);
00652     MCOS->EmitBytes("/");
00653   }
00654   const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles =
00655     MCOS->getContext().getMCDwarfFiles();
00656   MCOS->EmitBytes(MCDwarfFiles[1]->getName());
00657   MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
00658 
00659   // AT_comp_dir, the working directory the assembly was done in.
00660   MCOS->EmitBytes(context.getCompilationDir());
00661   MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
00662 
00663   // AT_APPLE_flags, the command line arguments of the assembler tool.
00664   StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
00665   if (!DwarfDebugFlags.empty()){
00666     MCOS->EmitBytes(DwarfDebugFlags);
00667     MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
00668   }
00669 
00670   // AT_producer, the version of the assembler tool.
00671   StringRef DwarfDebugProducer = context.getDwarfDebugProducer();
00672   if (!DwarfDebugProducer.empty()){
00673     MCOS->EmitBytes(DwarfDebugProducer);
00674   }
00675   else {
00676     MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM "));
00677     MCOS->EmitBytes(StringRef(PACKAGE_VERSION));
00678     MCOS->EmitBytes(StringRef(")"));
00679   }
00680   MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
00681 
00682   // AT_language, a 4 byte value.  We use DW_LANG_Mips_Assembler as the dwarf2
00683   // draft has no standard code for assembler.
00684   MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2);
00685 
00686   // Third part: the list of label DIEs.
00687 
00688   // Loop on saved info for dwarf labels and create the DIEs for them.
00689   const std::vector<const MCGenDwarfLabelEntry *> &Entries =
00690     MCOS->getContext().getMCGenDwarfLabelEntries();
00691   for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it =
00692        Entries.begin(), ie = Entries.end(); it != ie;
00693        ++it) {
00694     const MCGenDwarfLabelEntry *Entry = *it;
00695 
00696     // The DW_TAG_label DIE abbrev (2).
00697     MCOS->EmitULEB128IntValue(2);
00698 
00699     // AT_name, of the label without any leading underbar.
00700     MCOS->EmitBytes(Entry->getName());
00701     MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string.
00702 
00703     // AT_decl_file, index into the file table.
00704     MCOS->EmitIntValue(Entry->getFileNumber(), 4);
00705 
00706     // AT_decl_line, source line number.
00707     MCOS->EmitIntValue(Entry->getLineNumber(), 4);
00708 
00709     // AT_low_pc, start address of the label.
00710     const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry->getLabel(),
00711                                              MCSymbolRefExpr::VK_None, context);
00712     MCOS->EmitAbsValue(AT_low_pc, AddrSize);
00713 
00714     // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype.
00715     MCOS->EmitIntValue(0, 1);
00716 
00717     // The DW_TAG_unspecified_parameters DIE abbrev (3).
00718     MCOS->EmitULEB128IntValue(3);
00719 
00720     // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's.
00721     MCOS->EmitIntValue(0, 1);
00722   }
00723   // Deallocate the MCGenDwarfLabelEntry classes that saved away the info
00724   // for the dwarf labels.
00725   for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it =
00726        Entries.begin(), ie = Entries.end(); it != ie;
00727        ++it) {
00728     const MCGenDwarfLabelEntry *Entry = *it;
00729     delete Entry;
00730   }
00731 
00732   // Add the NULL DIE terminating the Compile Unit DIE's.
00733   MCOS->EmitIntValue(0, 1);
00734 
00735   // Now set the value of the symbol at the end of the info section.
00736   MCOS->EmitLabel(InfoEnd);
00737 }
00738 
00739 //
00740 // When generating dwarf for assembly source files this emits the Dwarf
00741 // sections.
00742 //
00743 void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) {
00744   // Create the dwarf sections in this order (.debug_line already created).
00745   MCContext &context = MCOS->getContext();
00746   const MCAsmInfo &AsmInfo = context.getAsmInfo();
00747   bool CreateDwarfSectionSymbols =
00748       AsmInfo.doesDwarfUseRelocationsAcrossSections();
00749   if (!CreateDwarfSectionSymbols)
00750     LineSectionSymbol = NULL;
00751   MCSymbol *AbbrevSectionSymbol = NULL;
00752   MCSymbol *InfoSectionSymbol = NULL;
00753   MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
00754   if (CreateDwarfSectionSymbols) {
00755     InfoSectionSymbol = context.CreateTempSymbol();
00756     MCOS->EmitLabel(InfoSectionSymbol);
00757   }
00758   MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
00759   if (CreateDwarfSectionSymbols) {
00760     AbbrevSectionSymbol = context.CreateTempSymbol();
00761     MCOS->EmitLabel(AbbrevSectionSymbol);
00762   }
00763   MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
00764 
00765   // If there are no line table entries then do not emit any section contents.
00766   if (context.getMCLineSections().empty())
00767     return;
00768 
00769   // Output the data for .debug_aranges section.
00770   EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
00771 
00772   // Output the data for .debug_abbrev section.
00773   EmitGenDwarfAbbrev(MCOS);
00774 
00775   // Output the data for .debug_info section.
00776   EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol);
00777 }
00778 
00779 //
00780 // When generating dwarf for assembly source files this is called when symbol
00781 // for a label is created.  If this symbol is not a temporary and is in the
00782 // section that dwarf is being generated for, save the needed info to create
00783 // a dwarf label.
00784 //
00785 void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
00786                                      SourceMgr &SrcMgr, SMLoc &Loc) {
00787   // We won't create dwarf labels for temporary symbols or symbols not in
00788   // the default text.
00789   if (Symbol->isTemporary())
00790     return;
00791   MCContext &context = MCOS->getContext();
00792   if (context.getGenDwarfSection() != MCOS->getCurrentSection().first)
00793     return;
00794 
00795   // The dwarf label's name does not have the symbol name's leading
00796   // underbar if any.
00797   StringRef Name = Symbol->getName();
00798   if (Name.startswith("_"))
00799     Name = Name.substr(1, Name.size()-1);
00800 
00801   // Get the dwarf file number to be used for the dwarf label.
00802   unsigned FileNumber = context.getGenDwarfFileNumber();
00803 
00804   // Finding the line number is the expensive part which is why we just don't
00805   // pass it in as for some symbols we won't create a dwarf label.
00806   int CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
00807   unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);
00808 
00809   // We create a temporary symbol for use for the AT_high_pc and AT_low_pc
00810   // values so that they don't have things like an ARM thumb bit from the
00811   // original symbol. So when used they won't get a low bit set after
00812   // relocation.
00813   MCSymbol *Label = context.CreateTempSymbol();
00814   MCOS->EmitLabel(Label);
00815 
00816   // Create and entry for the info and add it to the other entries.
00817   MCGenDwarfLabelEntry *Entry =
00818     new MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label);
00819   MCOS->getContext().addMCGenDwarfLabelEntry(Entry);
00820 }
00821 
00822 static int getDataAlignmentFactor(MCStreamer &streamer) {
00823   MCContext &context = streamer.getContext();
00824   const MCAsmInfo &asmInfo = context.getAsmInfo();
00825   int size = asmInfo.getCalleeSaveStackSlotSize();
00826   if (asmInfo.isStackGrowthDirectionUp())
00827     return size;
00828   else
00829     return -size;
00830 }
00831 
00832 static unsigned getSizeForEncoding(MCStreamer &streamer,
00833                                    unsigned symbolEncoding) {
00834   MCContext &context = streamer.getContext();
00835   unsigned format = symbolEncoding & 0x0f;
00836   switch (format) {
00837   default: llvm_unreachable("Unknown Encoding");
00838   case dwarf::DW_EH_PE_absptr:
00839   case dwarf::DW_EH_PE_signed:
00840     return context.getAsmInfo().getPointerSize();
00841   case dwarf::DW_EH_PE_udata2:
00842   case dwarf::DW_EH_PE_sdata2:
00843     return 2;
00844   case dwarf::DW_EH_PE_udata4:
00845   case dwarf::DW_EH_PE_sdata4:
00846     return 4;
00847   case dwarf::DW_EH_PE_udata8:
00848   case dwarf::DW_EH_PE_sdata8:
00849     return 8;
00850   }
00851 }
00852 
00853 static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
00854                        unsigned symbolEncoding, const char *comment = 0) {
00855   MCContext &context = streamer.getContext();
00856   const MCAsmInfo &asmInfo = context.getAsmInfo();
00857   const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol,
00858                                                 symbolEncoding,
00859                                                 streamer);
00860   unsigned size = getSizeForEncoding(streamer, symbolEncoding);
00861   if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment);
00862   streamer.EmitAbsValue(v, size);
00863 }
00864 
00865 static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
00866                             unsigned symbolEncoding) {
00867   MCContext &context = streamer.getContext();
00868   const MCAsmInfo &asmInfo = context.getAsmInfo();
00869   const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol,
00870                                                         symbolEncoding,
00871                                                         streamer);
00872   unsigned size = getSizeForEncoding(streamer, symbolEncoding);
00873   streamer.EmitValue(v, size);
00874 }
00875 
00876 namespace {
00877   class FrameEmitterImpl {
00878     int CFAOffset;
00879     int CIENum;
00880     bool UsingCFI;
00881     bool IsEH;
00882     const MCSymbol *SectionStart;
00883   public:
00884     FrameEmitterImpl(bool usingCFI, bool isEH)
00885       : CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH),
00886         SectionStart(0) {}
00887 
00888     void setSectionStart(const MCSymbol *Label) { SectionStart = Label; }
00889 
00890     /// EmitCompactUnwind - Emit the unwind information in a compact way. If
00891     /// we're successful, return 'true'. Otherwise, return 'false' and it will
00892     /// emit the normal CIE and FDE.
00893     void EmitCompactUnwind(MCStreamer &streamer,
00894                            const MCDwarfFrameInfo &frame);
00895 
00896     const MCSymbol &EmitCIE(MCStreamer &streamer,
00897                             const MCSymbol *personality,
00898                             unsigned personalityEncoding,
00899                             const MCSymbol *lsda,
00900                             bool IsSignalFrame,
00901                             unsigned lsdaEncoding);
00902     MCSymbol *EmitFDE(MCStreamer &streamer,
00903                       const MCSymbol &cieStart,
00904                       const MCDwarfFrameInfo &frame);
00905     void EmitCFIInstructions(MCStreamer &streamer,
00906                              const std::vector<MCCFIInstruction> &Instrs,
00907                              MCSymbol *BaseLabel);
00908     void EmitCFIInstruction(MCStreamer &Streamer,
00909                             const MCCFIInstruction &Instr);
00910   };
00911 
00912 } // end anonymous namespace
00913 
00914 static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding,
00915                              StringRef Prefix) {
00916   if (Streamer.isVerboseAsm()) {
00917     const char *EncStr;
00918     switch (Encoding) {
00919     default: EncStr = "<unknown encoding>"; break;
00920     case dwarf::DW_EH_PE_absptr: EncStr = "absptr"; break;
00921     case dwarf::DW_EH_PE_omit:   EncStr = "omit"; break;
00922     case dwarf::DW_EH_PE_pcrel:  EncStr = "pcrel"; break;
00923     case dwarf::DW_EH_PE_udata4: EncStr = "udata4"; break;
00924     case dwarf::DW_EH_PE_udata8: EncStr = "udata8"; break;
00925     case dwarf::DW_EH_PE_sdata4: EncStr = "sdata4"; break;
00926     case dwarf::DW_EH_PE_sdata8: EncStr = "sdata8"; break;
00927     case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
00928       EncStr = "pcrel udata4";
00929       break;
00930     case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
00931       EncStr = "pcrel sdata4";
00932       break;
00933     case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
00934       EncStr = "pcrel udata8";
00935       break;
00936     case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
00937       EncStr = "screl sdata8";
00938       break;
00939     case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4:
00940       EncStr = "indirect pcrel udata4";
00941       break;
00942     case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4:
00943       EncStr = "indirect pcrel sdata4";
00944       break;
00945     case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8:
00946       EncStr = "indirect pcrel udata8";
00947       break;
00948     case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8:
00949       EncStr = "indirect pcrel sdata8";
00950       break;
00951     }
00952 
00953     Streamer.AddComment(Twine(Prefix) + " = " + EncStr);
00954   }
00955 
00956   Streamer.EmitIntValue(Encoding, 1);
00957 }
00958 
00959 void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer,
00960                                           const MCCFIInstruction &Instr) {
00961   int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
00962   bool VerboseAsm = Streamer.isVerboseAsm();
00963 
00964   switch (Instr.getOperation()) {
00965   case MCCFIInstruction::OpRegister: {
00966     unsigned Reg1 = Instr.getRegister();
00967     unsigned Reg2 = Instr.getRegister2();
00968     if (VerboseAsm) {
00969       Streamer.AddComment("DW_CFA_register");
00970       Streamer.AddComment(Twine("Reg1 ") + Twine(Reg1));
00971       Streamer.AddComment(Twine("Reg2 ") + Twine(Reg2));
00972     }
00973     Streamer.EmitIntValue(dwarf::DW_CFA_register, 1);
00974     Streamer.EmitULEB128IntValue(Reg1);
00975     Streamer.EmitULEB128IntValue(Reg2);
00976     return;
00977   }
00978   case MCCFIInstruction::OpUndefined: {
00979     unsigned Reg = Instr.getRegister();
00980     if (VerboseAsm) {
00981       Streamer.AddComment("DW_CFA_undefined");
00982       Streamer.AddComment(Twine("Reg ") + Twine(Reg));
00983     }
00984     Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1);
00985     Streamer.EmitULEB128IntValue(Reg);
00986     return;
00987   }
00988   case MCCFIInstruction::OpAdjustCfaOffset:
00989   case MCCFIInstruction::OpDefCfaOffset: {
00990     const bool IsRelative =
00991       Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;
00992 
00993     if (VerboseAsm)
00994       Streamer.AddComment("DW_CFA_def_cfa_offset");
00995     Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);
00996 
00997     if (IsRelative)
00998       CFAOffset += Instr.getOffset();
00999     else
01000       CFAOffset = -Instr.getOffset();
01001 
01002     if (VerboseAsm)
01003       Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
01004     Streamer.EmitULEB128IntValue(CFAOffset);
01005 
01006     return;
01007   }
01008   case MCCFIInstruction::OpDefCfa: {
01009     if (VerboseAsm)
01010       Streamer.AddComment("DW_CFA_def_cfa");
01011     Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
01012 
01013     if (VerboseAsm)
01014       Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister()));
01015     Streamer.EmitULEB128IntValue(Instr.getRegister());
01016 
01017     CFAOffset = -Instr.getOffset();
01018 
01019     if (VerboseAsm)
01020       Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
01021     Streamer.EmitULEB128IntValue(CFAOffset);
01022 
01023     return;
01024   }
01025 
01026   case MCCFIInstruction::OpDefCfaRegister: {
01027     if (VerboseAsm)
01028       Streamer.AddComment("DW_CFA_def_cfa_register");
01029     Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
01030 
01031     if (VerboseAsm)
01032       Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister()));
01033     Streamer.EmitULEB128IntValue(Instr.getRegister());
01034 
01035     return;
01036   }
01037 
01038   case MCCFIInstruction::OpOffset:
01039   case MCCFIInstruction::OpRelOffset: {
01040     const bool IsRelative =
01041       Instr.getOperation() == MCCFIInstruction::OpRelOffset;
01042 
01043     unsigned Reg = Instr.getRegister();
01044     int Offset = Instr.getOffset();
01045     if (IsRelative)
01046       Offset -= CFAOffset;
01047     Offset = Offset / dataAlignmentFactor;
01048 
01049     if (Offset < 0) {
01050       if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf");
01051       Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1);
01052       if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
01053       Streamer.EmitULEB128IntValue(Reg);
01054       if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
01055       Streamer.EmitSLEB128IntValue(Offset);
01056     } else if (Reg < 64) {
01057       if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") +
01058                                           Twine(Reg) + ")");
01059       Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1);
01060       if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
01061       Streamer.EmitULEB128IntValue(Offset);
01062     } else {
01063       if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended");
01064       Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1);
01065       if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
01066       Streamer.EmitULEB128IntValue(Reg);
01067       if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
01068       Streamer.EmitULEB128IntValue(Offset);
01069     }
01070     return;
01071   }
01072   case MCCFIInstruction::OpRememberState:
01073     if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state");
01074     Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1);
01075     return;
01076   case MCCFIInstruction::OpRestoreState:
01077     if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state");
01078     Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
01079     return;
01080   case MCCFIInstruction::OpSameValue: {
01081     unsigned Reg = Instr.getRegister();
01082     if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value");
01083     Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1);
01084     if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
01085     Streamer.EmitULEB128IntValue(Reg);
01086     return;
01087   }
01088   case MCCFIInstruction::OpRestore: {
01089     unsigned Reg = Instr.getRegister();
01090     if (VerboseAsm) {
01091       Streamer.AddComment("DW_CFA_restore");
01092       Streamer.AddComment(Twine("Reg ") + Twine(Reg));
01093     }
01094     Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
01095     return;
01096   }
01097   case MCCFIInstruction::OpEscape:
01098     if (VerboseAsm) Streamer.AddComment("Escape bytes");
01099     Streamer.EmitBytes(Instr.getValues());
01100     return;
01101   }
01102   llvm_unreachable("Unhandled case in switch");
01103 }
01104 
01105 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
01106 /// frame.
01107 void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer,
01108                                     const std::vector<MCCFIInstruction> &Instrs,
01109                                            MCSymbol *BaseLabel) {
01110   for (unsigned i = 0, N = Instrs.size(); i < N; ++i) {
01111     const MCCFIInstruction &Instr = Instrs[i];
01112     MCSymbol *Label = Instr.getLabel();
01113     // Throw out move if the label is invalid.
01114     if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.
01115 
01116     // Advance row if new location.
01117     if (BaseLabel && Label) {
01118       MCSymbol *ThisSym = Label;
01119       if (ThisSym != BaseLabel) {
01120         if (streamer.isVerboseAsm()) streamer.AddComment("DW_CFA_advance_loc4");
01121         streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
01122         BaseLabel = ThisSym;
01123       }
01124     }
01125 
01126     EmitCFIInstruction(streamer, Instr);
01127   }
01128 }
01129 
01130 /// EmitCompactUnwind - Emit the unwind information in a compact way. If we're
01131 /// successful, return 'true'. Otherwise, return 'false' and it will emit the
01132 /// normal CIE and FDE.
01133 void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
01134                                          const MCDwarfFrameInfo &Frame) {
01135   MCContext &Context = Streamer.getContext();
01136   const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
01137   bool VerboseAsm = Streamer.isVerboseAsm();
01138 
01139   // range-start range-length  compact-unwind-enc personality-func   lsda
01140   //  _foo       LfooEnd-_foo  0x00000023          0                 0
01141   //  _bar       LbarEnd-_bar  0x00000025         __gxx_personality  except_tab1
01142   //
01143   //   .section __LD,__compact_unwind,regular,debug
01144   //
01145   //   # compact unwind for _foo
01146   //   .quad _foo
01147   //   .set L1,LfooEnd-_foo
01148   //   .long L1
01149   //   .long 0x01010001
01150   //   .quad 0
01151   //   .quad 0
01152   //
01153   //   # compact unwind for _bar
01154   //   .quad _bar
01155   //   .set L2,LbarEnd-_bar
01156   //   .long L2
01157   //   .long 0x01020011
01158   //   .quad __gxx_personality
01159   //   .quad except_tab1
01160 
01161   uint32_t Encoding = Frame.CompactUnwindEncoding;
01162   if (!Encoding) return;
01163   bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly());
01164 
01165   // The encoding needs to know we have an LSDA.
01166   if (!DwarfEHFrameOnly && Frame.Lsda)
01167     Encoding |= 0x40000000;
01168 
01169   // Range Start
01170   unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI);
01171   unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
01172   if (VerboseAsm) Streamer.AddComment("Range Start");
01173   Streamer.EmitSymbolValue(Frame.Function, Size);
01174 
01175   // Range Length
01176   const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin,
01177                                               *Frame.End, 0);
01178   if (VerboseAsm) Streamer.AddComment("Range Length");
01179   Streamer.EmitAbsValue(Range, 4);
01180 
01181   // Compact Encoding
01182   Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
01183   if (VerboseAsm) Streamer.AddComment("Compact Unwind Encoding: 0x" +
01184                                       Twine::utohexstr(Encoding));
01185   Streamer.EmitIntValue(Encoding, Size);
01186 
01187   // Personality Function
01188   Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);
01189   if (VerboseAsm) Streamer.AddComment("Personality Function");
01190   if (!DwarfEHFrameOnly && Frame.Personality)
01191     Streamer.EmitSymbolValue(Frame.Personality, Size);
01192   else
01193     Streamer.EmitIntValue(0, Size); // No personality fn
01194 
01195   // LSDA
01196   Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);
01197   if (VerboseAsm) Streamer.AddComment("LSDA");
01198   if (!DwarfEHFrameOnly && Frame.Lsda)
01199     Streamer.EmitSymbolValue(Frame.Lsda, Size);
01200   else
01201     Streamer.EmitIntValue(0, Size); // No LSDA
01202 }
01203 
01204 const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
01205                                           const MCSymbol *personality,
01206                                           unsigned personalityEncoding,
01207                                           const MCSymbol *lsda,
01208                                           bool IsSignalFrame,
01209                                           unsigned lsdaEncoding) {
01210   MCContext &context = streamer.getContext();
01211   const MCRegisterInfo &MRI = context.getRegisterInfo();
01212   const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
01213   bool verboseAsm = streamer.isVerboseAsm();
01214 
01215   MCSymbol *sectionStart;
01216   if (MOFI->isFunctionEHFrameSymbolPrivate() || !IsEH)
01217     sectionStart = context.CreateTempSymbol();
01218   else
01219     sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum));
01220 
01221   streamer.EmitLabel(sectionStart);
01222   CIENum++;
01223 
01224   MCSymbol *sectionEnd = context.CreateTempSymbol();
01225 
01226   // Length
01227   const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart,
01228                                                *sectionEnd, 4);
01229   if (verboseAsm) streamer.AddComment("CIE Length");
01230   streamer.EmitAbsValue(Length, 4);
01231 
01232   // CIE ID
01233   unsigned CIE_ID = IsEH ? 0 : -1;
01234   if (verboseAsm) streamer.AddComment("CIE ID Tag");
01235   streamer.EmitIntValue(CIE_ID, 4);
01236 
01237   // Version
01238   if (verboseAsm) streamer.AddComment("DW_CIE_VERSION");
01239   streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1);
01240 
01241   // Augmentation String
01242   SmallString<8> Augmentation;
01243   if (IsEH) {
01244     if (verboseAsm) streamer.AddComment("CIE Augmentation");
01245     Augmentation += "z";
01246     if (personality)
01247       Augmentation += "P";
01248     if (lsda)
01249       Augmentation += "L";
01250     Augmentation += "R";
01251     if (IsSignalFrame)
01252       Augmentation += "S";
01253     streamer.EmitBytes(Augmentation.str());
01254   }
01255   streamer.EmitIntValue(0, 1);
01256 
01257   // Code Alignment Factor
01258   if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor");
01259   streamer.EmitULEB128IntValue(1);
01260 
01261   // Data Alignment Factor
01262   if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor");
01263   streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer));
01264 
01265   // Return Address Register
01266   if (verboseAsm) streamer.AddComment("CIE Return Address Column");
01267   streamer.EmitULEB128IntValue(MRI.getDwarfRegNum(MRI.getRARegister(), true));
01268 
01269   // Augmentation Data Length (optional)
01270 
01271   unsigned augmentationLength = 0;
01272   if (IsEH) {
01273     if (personality) {
01274       // Personality Encoding
01275       augmentationLength += 1;
01276       // Personality
01277       augmentationLength += getSizeForEncoding(streamer, personalityEncoding);
01278     }
01279     if (lsda)
01280       augmentationLength += 1;
01281     // Encoding of the FDE pointers
01282     augmentationLength += 1;
01283 
01284     if (verboseAsm) streamer.AddComment("Augmentation Size");
01285     streamer.EmitULEB128IntValue(augmentationLength);
01286 
01287     // Augmentation Data (optional)
01288     if (personality) {
01289       // Personality Encoding
01290       EmitEncodingByte(streamer, personalityEncoding,
01291                        "Personality Encoding");
01292       // Personality
01293       if (verboseAsm) streamer.AddComment("Personality");
01294       EmitPersonality(streamer, *personality, personalityEncoding);
01295     }
01296 
01297     if (lsda)
01298       EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding");
01299 
01300     // Encoding of the FDE pointers
01301     EmitEncodingByte(streamer, MOFI->getFDEEncoding(UsingCFI),
01302                      "FDE Encoding");
01303   }
01304 
01305   // Initial Instructions
01306 
01307   const MCAsmInfo &MAI = context.getAsmInfo();
01308   const std::vector<MCCFIInstruction> &Instructions =
01309       MAI.getInitialFrameState();
01310   EmitCFIInstructions(streamer, Instructions, NULL);
01311 
01312   // Padding
01313   streamer.EmitValueToAlignment(IsEH
01314                                 ? 4 : context.getAsmInfo().getPointerSize());
01315 
01316   streamer.EmitLabel(sectionEnd);
01317   return *sectionStart;
01318 }
01319 
01320 MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,
01321                                     const MCSymbol &cieStart,
01322                                     const MCDwarfFrameInfo &frame) {
01323   MCContext &context = streamer.getContext();
01324   MCSymbol *fdeStart = context.CreateTempSymbol();
01325   MCSymbol *fdeEnd = context.CreateTempSymbol();
01326   const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
01327   bool verboseAsm = streamer.isVerboseAsm();
01328 
01329   if (IsEH && frame.Function && !MOFI->isFunctionEHFrameSymbolPrivate()) {
01330     MCSymbol *EHSym =
01331       context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh"));
01332     streamer.EmitEHSymAttributes(frame.Function, EHSym);
01333     streamer.EmitLabel(EHSym);
01334   }
01335 
01336   // Length
01337   const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0);
01338   if (verboseAsm) streamer.AddComment("FDE Length");
01339   streamer.EmitAbsValue(Length, 4);
01340 
01341   streamer.EmitLabel(fdeStart);
01342 
01343   // CIE Pointer
01344   const MCAsmInfo &asmInfo = context.getAsmInfo();
01345   if (IsEH) {
01346     const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart,
01347                                                  0);
01348     if (verboseAsm) streamer.AddComment("FDE CIE Offset");
01349     streamer.EmitAbsValue(offset, 4);
01350   } else if (!asmInfo.doesDwarfUseRelocationsAcrossSections()) {
01351     const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart,
01352                                                  cieStart, 0);
01353     streamer.EmitAbsValue(offset, 4);
01354   } else {
01355     streamer.EmitSymbolValue(&cieStart, 4);
01356   }
01357 
01358   // PC Begin
01359   unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding(UsingCFI)
01360                              : (unsigned)dwarf::DW_EH_PE_absptr;
01361   unsigned PCSize = getSizeForEncoding(streamer, PCEncoding);
01362   EmitSymbol(streamer, *frame.Begin, PCEncoding, "FDE initial location");
01363 
01364   // PC Range
01365   const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin,
01366                                               *frame.End, 0);
01367   if (verboseAsm) streamer.AddComment("FDE address range");
01368   streamer.EmitAbsValue(Range, PCSize);
01369 
01370   if (IsEH) {
01371     // Augmentation Data Length
01372     unsigned augmentationLength = 0;
01373 
01374     if (frame.Lsda)
01375       augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding);
01376 
01377     if (verboseAsm) streamer.AddComment("Augmentation size");
01378     streamer.EmitULEB128IntValue(augmentationLength);
01379 
01380     // Augmentation Data
01381     if (frame.Lsda)
01382       EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding,
01383                  "Language Specific Data Area");
01384   }
01385 
01386   // Call Frame Instructions
01387   EmitCFIInstructions(streamer, frame.Instructions, frame.Begin);
01388 
01389   // Padding
01390   streamer.EmitValueToAlignment(PCSize);
01391 
01392   return fdeEnd;
01393 }
01394 
01395 namespace {
01396   struct CIEKey {
01397     static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false); }
01398     static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false); }
01399 
01400     CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_,
01401            unsigned LsdaEncoding_, bool IsSignalFrame_) :
01402       Personality(Personality_), PersonalityEncoding(PersonalityEncoding_),
01403       LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_) {
01404     }
01405     const MCSymbol* Personality;
01406     unsigned PersonalityEncoding;
01407     unsigned LsdaEncoding;
01408     bool IsSignalFrame;
01409   };
01410 }
01411 
01412 namespace llvm {
01413   template <>
01414   struct DenseMapInfo<CIEKey> {
01415     static CIEKey getEmptyKey() {
01416       return CIEKey::getEmptyKey();
01417     }
01418     static CIEKey getTombstoneKey() {
01419       return CIEKey::getTombstoneKey();
01420     }
01421     static unsigned getHashValue(const CIEKey &Key) {
01422       return static_cast<unsigned>(hash_combine(Key.Personality,
01423                                                 Key.PersonalityEncoding,
01424                                                 Key.LsdaEncoding,
01425                                                 Key.IsSignalFrame));
01426     }
01427     static bool isEqual(const CIEKey &LHS,
01428                         const CIEKey &RHS) {
01429       return LHS.Personality == RHS.Personality &&
01430         LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
01431         LHS.LsdaEncoding == RHS.LsdaEncoding &&
01432         LHS.IsSignalFrame == RHS.IsSignalFrame;
01433     }
01434   };
01435 }
01436 
01437 void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer,
01438                                bool UsingCFI,
01439                                bool IsEH) {
01440   MCContext &Context = Streamer.getContext();
01441   MCObjectFileInfo *MOFI =
01442     const_cast<MCObjectFileInfo*>(Context.getObjectFileInfo());
01443   FrameEmitterImpl Emitter(UsingCFI, IsEH);
01444   ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos();
01445 
01446   // Emit the compact unwind info if available.
01447   if (IsEH && MOFI->getCompactUnwindSection()) {
01448     bool SectionEmitted = false;
01449     for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
01450       const MCDwarfFrameInfo &Frame = FrameArray[i];
01451       if (Frame.CompactUnwindEncoding == 0) continue;
01452       if (!SectionEmitted) {
01453         Streamer.SwitchSection(MOFI->getCompactUnwindSection());
01454         Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize());
01455         SectionEmitted = true;
01456       }
01457       Emitter.EmitCompactUnwind(Streamer, Frame);
01458     }
01459   }
01460 
01461   const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() :
01462                                     *MOFI->getDwarfFrameSection();
01463   Streamer.SwitchSection(&Section);
01464   MCSymbol *SectionStart = Context.CreateTempSymbol();
01465   Streamer.EmitLabel(SectionStart);
01466   Emitter.setSectionStart(SectionStart);
01467 
01468   MCSymbol *FDEEnd = NULL;
01469   DenseMap<CIEKey, const MCSymbol*> CIEStarts;
01470 
01471   const MCSymbol *DummyDebugKey = NULL;
01472   for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) {
01473     const MCDwarfFrameInfo &Frame = FrameArray[i];
01474     CIEKey Key(Frame.Personality, Frame.PersonalityEncoding,
01475                Frame.LsdaEncoding, Frame.IsSignalFrame);
01476     const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
01477     if (!CIEStart)
01478       CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality,
01479                                   Frame.PersonalityEncoding, Frame.Lsda,
01480                                   Frame.IsSignalFrame,
01481                                   Frame.LsdaEncoding);
01482 
01483     FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame);
01484 
01485     if (i != n - 1)
01486       Streamer.EmitLabel(FDEEnd);
01487   }
01488 
01489   Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize());
01490   if (FDEEnd)
01491     Streamer.EmitLabel(FDEEnd);
01492 }
01493 
01494 void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer,
01495                                          uint64_t AddrDelta) {
01496   SmallString<256> Tmp;
01497   raw_svector_ostream OS(Tmp);
01498   MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS);
01499   Streamer.EmitBytes(OS.str());
01500 }
01501 
01502 void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta,
01503                                            raw_ostream &OS) {
01504   // FIXME: Assumes the code alignment factor is 1.
01505   if (AddrDelta == 0) {
01506   } else if (isUIntN(6, AddrDelta)) {
01507     uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
01508     OS << Opcode;
01509   } else if (isUInt<8>(AddrDelta)) {
01510     OS << uint8_t(dwarf::DW_CFA_advance_loc1);
01511     OS << uint8_t(AddrDelta);
01512   } else if (isUInt<16>(AddrDelta)) {
01513     // FIXME: check what is the correct behavior on a big endian machine.
01514     OS << uint8_t(dwarf::DW_CFA_advance_loc2);
01515     OS << uint8_t( AddrDelta       & 0xff);
01516     OS << uint8_t((AddrDelta >> 8) & 0xff);
01517   } else {
01518     // FIXME: check what is the correct behavior on a big endian machine.
01519     assert(isUInt<32>(AddrDelta));
01520     OS << uint8_t(dwarf::DW_CFA_advance_loc4);
01521     OS << uint8_t( AddrDelta        & 0xff);
01522     OS << uint8_t((AddrDelta >> 8)  & 0xff);
01523     OS << uint8_t((AddrDelta >> 16) & 0xff);
01524     OS << uint8_t((AddrDelta >> 24) & 0xff);
01525 
01526   }
01527 }