| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 1 | //===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
|  | 10 | #include "llvm/MC/MCDwarf.h" | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 11 | #include "llvm/MC/MCAssembler.h" | 
|  | 12 | #include "llvm/MC/MCSymbol.h" | 
|  | 13 | #include "llvm/MC/MCExpr.h" | 
|  | 14 | #include "llvm/MC/MCContext.h" | 
|  | 15 | #include "llvm/MC/MCObjectWriter.h" | 
|  | 16 | #include "llvm/ADT/SmallString.h" | 
| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 17 | #include "llvm/Support/Debug.h" | 
|  | 18 | #include "llvm/Support/raw_ostream.h" | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 19 | #include "llvm/Target/TargetAsmBackend.h" | 
| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 20 | using namespace llvm; | 
|  | 21 |  | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 22 | // Given a special op, return the address skip amount (in units of | 
|  | 23 | // DWARF2_LINE_MIN_INSN_LENGTH. | 
|  | 24 | #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) | 
|  | 25 |  | 
|  | 26 | // The maximum address skip amount that can be encoded with a special op. | 
|  | 27 | #define MAX_SPECIAL_ADDR_DELTA		SPECIAL_ADDR(255) | 
|  | 28 |  | 
|  | 29 | // First special line opcode - leave room for the standard opcodes. | 
|  | 30 | // Note: If you want to change this, you'll have to update the | 
|  | 31 | // "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit(). | 
|  | 32 | #define DWARF2_LINE_OPCODE_BASE		13 | 
|  | 33 |  | 
|  | 34 | // Minimum line offset in a special line info. opcode.  This value | 
|  | 35 | // was chosen to give a reasonable range of values. | 
|  | 36 | #define DWARF2_LINE_BASE		-5 | 
|  | 37 |  | 
|  | 38 | // Range of line offsets in a special line info. opcode. | 
|  | 39 | # define DWARF2_LINE_RANGE		14 | 
|  | 40 |  | 
|  | 41 | // Define the architecture-dependent minimum instruction length (in bytes). | 
|  | 42 | // This value should be rather too small than too big. | 
|  | 43 | # define DWARF2_LINE_MIN_INSN_LENGTH	1 | 
|  | 44 |  | 
|  | 45 | // Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting, | 
|  | 46 | // this routine is a nop and will be optimized away. | 
|  | 47 | static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) | 
|  | 48 | { | 
|  | 49 | if (DWARF2_LINE_MIN_INSN_LENGTH == 1) | 
|  | 50 | return AddrDelta; | 
|  | 51 | if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) { | 
|  | 52 | // TODO: report this error, but really only once. | 
|  | 53 | ; | 
|  | 54 | } | 
|  | 55 | return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH; | 
|  | 56 | } | 
|  | 57 |  | 
|  | 58 | // | 
|  | 59 | // This is called when an instruction is assembled into the specified section | 
|  | 60 | // and if there is information from the last .loc directive that has yet to have | 
|  | 61 | // a line entry made for it is made. | 
|  | 62 | // | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 63 | void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) { | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 64 | if (!MCOS->getContext().getDwarfLocSeen()) | 
|  | 65 | return; | 
|  | 66 |  | 
|  | 67 | // Create a symbol at in the current section for use in the line entry. | 
|  | 68 | MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol(); | 
|  | 69 | // Set the value of the symbol to use for the MCLineEntry. | 
|  | 70 | MCOS->EmitLabel(LineSym); | 
|  | 71 |  | 
|  | 72 | // Get the current .loc info saved in the context. | 
|  | 73 | const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc(); | 
|  | 74 |  | 
|  | 75 | // Create a (local) line entry with the symbol and the current .loc info. | 
|  | 76 | MCLineEntry LineEntry(LineSym, DwarfLoc); | 
|  | 77 |  | 
|  | 78 | // clear DwarfLocSeen saying the current .loc info is now used. | 
| Kevin Enderby | 3f55c24 | 2010-10-04 20:17:24 +0000 | [diff] [blame] | 79 | MCOS->getContext().ClearDwarfLocSeen(); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 80 |  | 
|  | 81 | // Get the MCLineSection for this section, if one does not exist for this | 
|  | 82 | // section create it. | 
|  | 83 | DenseMap<const MCSection *, MCLineSection *> &MCLineSections = | 
|  | 84 | MCOS->getContext().getMCLineSections(); | 
|  | 85 | MCLineSection *LineSection = MCLineSections[Section]; | 
|  | 86 | if (!LineSection) { | 
|  | 87 | // Create a new MCLineSection.  This will be deleted after the dwarf line | 
|  | 88 | // table is created using it by iterating through the MCLineSections | 
|  | 89 | // DenseMap. | 
|  | 90 | LineSection = new MCLineSection; | 
|  | 91 | // Save a pointer to the new LineSection into the MCLineSections DenseMap. | 
|  | 92 | MCLineSections[Section] = LineSection; | 
|  | 93 | } | 
|  | 94 |  | 
|  | 95 | // Add the line entry to this section's entries. | 
|  | 96 | LineSection->addLineEntry(LineEntry); | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | // | 
|  | 100 | // This helper routine returns an expression of End - Start + IntVal . | 
|  | 101 | // | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 102 | static inline const MCExpr *MakeStartMinusEndExpr(MCStreamer *MCOS, | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 103 | MCSymbol *Start, | 
|  | 104 | MCSymbol *End, int IntVal) { | 
|  | 105 | MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; | 
|  | 106 | const MCExpr *Res = | 
|  | 107 | MCSymbolRefExpr::Create(End, Variant, MCOS->getContext()); | 
|  | 108 | const MCExpr *RHS = | 
|  | 109 | MCSymbolRefExpr::Create(Start, Variant, MCOS->getContext()); | 
|  | 110 | const MCExpr *Res1 = | 
|  | 111 | MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS->getContext()); | 
|  | 112 | const MCExpr *Res2 = | 
|  | 113 | MCConstantExpr::Create(IntVal, MCOS->getContext()); | 
|  | 114 | const MCExpr *Res3 = | 
|  | 115 | MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS->getContext()); | 
|  | 116 | return Res3; | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | // | 
|  | 120 | // This emits an "absolute" address used in the start of a dwarf line number | 
|  | 121 | // table.  This will result in a relocatation entry for the address. | 
|  | 122 | // | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 123 | static inline void EmitDwarfSetAddress(MCStreamer *MCOS, | 
|  | 124 | MCSymbol *Symbol, | 
|  | 125 | int PointerSize) { | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 126 | MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); | 
|  | 127 |  | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 128 | MCOS->EmitULEB128IntValue(PointerSize + 1); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 129 |  | 
|  | 130 | MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1); | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 131 | MCOS->EmitSymbolValue(Symbol, PointerSize); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 132 | } | 
|  | 133 |  | 
|  | 134 | // | 
|  | 135 | // This emits the Dwarf line table for the specified section from the entries | 
|  | 136 | // in the LineSection. | 
|  | 137 | // | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 138 | static inline void EmitDwarfLineTable(MCStreamer *MCOS, | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 139 | const MCSection *Section, | 
|  | 140 | MCLineSection *LineSection, | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 141 | const MCSection *DwarfLineSection, | 
|  | 142 | MCSectionData *DLS, | 
|  | 143 | int PointerSize) { | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 144 | unsigned FileNum = 1; | 
|  | 145 | unsigned LastLine = 1; | 
|  | 146 | unsigned Column = 0; | 
|  | 147 | unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; | 
|  | 148 | unsigned Isa = 0; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 149 | MCSymbol *LastLabel = NULL; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 150 |  | 
|  | 151 | // Loop through each MCLineEntry and encode the dwarf line number table. | 
|  | 152 | for (MCLineSection::iterator | 
|  | 153 | it = LineSection->getMCLineEntries()->begin(), | 
|  | 154 | ie = LineSection->getMCLineEntries()->end(); it != ie; ++it) { | 
|  | 155 |  | 
|  | 156 | if (FileNum != it->getFileNum()) { | 
|  | 157 | FileNum = it->getFileNum(); | 
|  | 158 | MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1); | 
| Rafael Espindola | 3ff5709 | 2010-11-02 17:22:24 +0000 | [diff] [blame] | 159 | MCOS->EmitULEB128IntValue(FileNum); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 160 | } | 
|  | 161 | if (Column != it->getColumn()) { | 
|  | 162 | Column = it->getColumn(); | 
|  | 163 | MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); | 
| Rafael Espindola | 3ff5709 | 2010-11-02 17:22:24 +0000 | [diff] [blame] | 164 | MCOS->EmitULEB128IntValue(Column); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 165 | } | 
|  | 166 | if (Isa != it->getIsa()) { | 
|  | 167 | Isa = it->getIsa(); | 
|  | 168 | MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); | 
| Rafael Espindola | 3ff5709 | 2010-11-02 17:22:24 +0000 | [diff] [blame] | 169 | MCOS->EmitULEB128IntValue(Isa); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 170 | } | 
|  | 171 | if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { | 
|  | 172 | Flags = it->getFlags(); | 
|  | 173 | MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); | 
|  | 174 | } | 
|  | 175 | if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK) | 
|  | 176 | MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); | 
|  | 177 | if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END) | 
|  | 178 | MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); | 
|  | 179 | if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) | 
|  | 180 | MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); | 
|  | 181 |  | 
| Rafael Espindola | 64185cc | 2010-11-13 01:06:27 +0000 | [diff] [blame] | 182 | int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 183 | MCSymbol *Label = it->getLabel(); | 
|  | 184 |  | 
|  | 185 | // At this point we want to emit/create the sequence to encode the delta in | 
|  | 186 | // line numbers and the increment of the address from the previous Label | 
|  | 187 | // and the current Label. | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 188 | if (LastLabel == NULL || DLS == NULL) { | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 189 | // emit the sequence to set the address | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 190 | EmitDwarfSetAddress(MCOS, Label, PointerSize); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 191 | // emit the sequence for the LineDelta (from 1) and a zero address delta. | 
|  | 192 | MCDwarfLineAddr::Emit(MCOS, LineDelta, 0); | 
|  | 193 | } | 
|  | 194 | else { | 
|  | 195 | // Create an expression for the address delta from the LastLabel and | 
|  | 196 | // this Label (plus 0). | 
|  | 197 | const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, Label,0); | 
|  | 198 | // Create a Dwarf Line fragment for the LineDelta and AddrDelta. | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 199 | new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, DLS); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 200 | } | 
|  | 201 |  | 
|  | 202 | LastLine = it->getLine(); | 
|  | 203 | LastLabel = Label; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 204 | } | 
|  | 205 |  | 
|  | 206 | // Emit a DW_LNE_end_sequence for the end of the section. | 
|  | 207 | // Using the pointer Section create a temporary label at the end of the | 
|  | 208 | // section and use that and the LastLabel to compute the address delta | 
|  | 209 | // and use INT64_MAX as the line delta which is the signal that this is | 
|  | 210 | // actually a DW_LNE_end_sequence. | 
|  | 211 |  | 
|  | 212 | // Switch to the section to be able to create a symbol at its end. | 
|  | 213 | MCOS->SwitchSection(Section); | 
|  | 214 | // Create a symbol at the end of the section. | 
|  | 215 | MCSymbol *SectionEnd = MCOS->getContext().CreateTempSymbol(); | 
|  | 216 | // Set the value of the symbol, as we are at the end of the section. | 
|  | 217 | MCOS->EmitLabel(SectionEnd); | 
|  | 218 |  | 
|  | 219 | // Switch back the the dwarf line section. | 
|  | 220 | MCOS->SwitchSection(DwarfLineSection); | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 221 |  | 
|  | 222 | if (DLS == NULL) { | 
|  | 223 | // emit the sequence to set the address | 
|  | 224 | EmitDwarfSetAddress(MCOS, SectionEnd, PointerSize); | 
|  | 225 | // emit the sequence for the LineDelta (from 1) and a zero address delta. | 
|  | 226 | MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0); | 
|  | 227 | } else { | 
|  | 228 | // Create an expression for the address delta from the LastLabel and this | 
|  | 229 | // SectionEnd label. | 
|  | 230 | const MCExpr *AddrDelta = MakeStartMinusEndExpr(MCOS, LastLabel, SectionEnd, | 
|  | 231 | 0); | 
|  | 232 | // Create a Dwarf Line fragment for the LineDelta and AddrDelta. | 
|  | 233 | new MCDwarfLineAddrFragment(INT64_MAX, *AddrDelta, DLS); | 
|  | 234 | } | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 235 | } | 
|  | 236 |  | 
|  | 237 | // | 
|  | 238 | // This emits the Dwarf file and the line tables. | 
|  | 239 | // | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 240 | void MCDwarfFileTable::Emit(MCStreamer *MCOS, | 
|  | 241 | const MCSection *DwarfLineSection, | 
|  | 242 | MCSectionData *DLS, | 
|  | 243 | int PointerSize) { | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 244 | // Switch to the section where the table will be emitted into. | 
|  | 245 | MCOS->SwitchSection(DwarfLineSection); | 
|  | 246 |  | 
|  | 247 | // Create a symbol at the beginning of this section. | 
|  | 248 | MCSymbol *LineStartSym = MCOS->getContext().CreateTempSymbol(); | 
|  | 249 | // Set the value of the symbol, as we are at the start of the section. | 
|  | 250 | MCOS->EmitLabel(LineStartSym); | 
|  | 251 |  | 
|  | 252 | // Create a symbol for the end of the section (to be set when we get there). | 
|  | 253 | MCSymbol *LineEndSym = MCOS->getContext().CreateTempSymbol(); | 
|  | 254 |  | 
|  | 255 | // The first 4 bytes is the total length of the information for this | 
|  | 256 | // compilation unit (not including these 4 bytes for the length). | 
|  | 257 | MCOS->EmitValue(MakeStartMinusEndExpr(MCOS, LineStartSym, LineEndSym, 4), | 
|  | 258 | 4, 0); | 
|  | 259 |  | 
|  | 260 | // Next 2 bytes is the Version, which is Dwarf 2. | 
|  | 261 | MCOS->EmitIntValue(2, 2); | 
|  | 262 |  | 
|  | 263 | // Create a symbol for the end of the prologue (to be set when we get there). | 
|  | 264 | MCSymbol *ProEndSym = MCOS->getContext().CreateTempSymbol(); // Lprologue_end | 
|  | 265 |  | 
|  | 266 | // Length of the prologue, is the next 4 bytes.  Which is the start of the | 
|  | 267 | // section to the end of the prologue.  Not including the 4 bytes for the | 
|  | 268 | // total length, the 2 bytes for the version, and these 4 bytes for the | 
|  | 269 | // length of the prologue. | 
|  | 270 | MCOS->EmitValue(MakeStartMinusEndExpr(MCOS, LineStartSym, ProEndSym, | 
|  | 271 | (4 + 2 + 4)), | 
|  | 272 | 4, 0); | 
|  | 273 |  | 
|  | 274 | // Parameters of the state machine, are next. | 
|  | 275 | MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); | 
|  | 276 | MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); | 
|  | 277 | MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); | 
|  | 278 | MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); | 
|  | 279 | MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1); | 
|  | 280 |  | 
|  | 281 | // Standard opcode lengths | 
|  | 282 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy | 
|  | 283 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc | 
|  | 284 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line | 
|  | 285 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file | 
|  | 286 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column | 
|  | 287 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt | 
|  | 288 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block | 
|  | 289 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc | 
|  | 290 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc | 
|  | 291 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end | 
|  | 292 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin | 
|  | 293 | MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa | 
|  | 294 |  | 
|  | 295 | // Put out the directory and file tables. | 
|  | 296 |  | 
|  | 297 | // First the directory table. | 
|  | 298 | const std::vector<StringRef> &MCDwarfDirs = | 
|  | 299 | MCOS->getContext().getMCDwarfDirs(); | 
|  | 300 | for (unsigned i = 0; i < MCDwarfDirs.size(); i++) { | 
|  | 301 | MCOS->EmitBytes(MCDwarfDirs[i], 0); // the DirectoryName | 
|  | 302 | MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string | 
|  | 303 | } | 
|  | 304 | MCOS->EmitIntValue(0, 1); // Terminate the directory list | 
|  | 305 |  | 
|  | 306 | // Second the file table. | 
|  | 307 | const std::vector<MCDwarfFile *> &MCDwarfFiles = | 
|  | 308 | MCOS->getContext().getMCDwarfFiles(); | 
|  | 309 | for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { | 
|  | 310 | MCOS->EmitBytes(MCDwarfFiles[i]->getName(), 0); // FileName | 
|  | 311 | MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string | 
| Rafael Espindola | 3ff5709 | 2010-11-02 17:22:24 +0000 | [diff] [blame] | 312 | // the Directory num | 
|  | 313 | MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex()); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 314 | MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0) | 
|  | 315 | MCOS->EmitIntValue(0, 1); // filesize (always 0) | 
|  | 316 | } | 
|  | 317 | MCOS->EmitIntValue(0, 1); // Terminate the file list | 
|  | 318 |  | 
|  | 319 | // This is the end of the prologue, so set the value of the symbol at the | 
|  | 320 | // end of the prologue (that was used in a previous expression). | 
|  | 321 | MCOS->EmitLabel(ProEndSym); | 
|  | 322 |  | 
|  | 323 | // Put out the line tables. | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 324 | DenseMap<const MCSection *, MCLineSection *> &MCLineSections = | 
|  | 325 | MCOS->getContext().getMCLineSections(); | 
|  | 326 | for (DenseMap<const MCSection *, MCLineSection *>::iterator it = | 
|  | 327 | MCLineSections.begin(), ie = MCLineSections.end(); it != ie; ++it) { | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 328 | EmitDwarfLineTable(MCOS, it->first, it->second, DwarfLineSection, DLS, | 
|  | 329 | PointerSize); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 330 |  | 
|  | 331 | // Now delete the MCLineSections that were created in MCLineEntry::Make() | 
|  | 332 | // and used to emit the line table. | 
|  | 333 | delete it->second; | 
|  | 334 | } | 
|  | 335 |  | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 336 | // This is the end of the section, so set the value of the symbol at the end | 
|  | 337 | // of this section (that was used in a previous expression). | 
|  | 338 | MCOS->EmitLabel(LineEndSym); | 
|  | 339 | } | 
|  | 340 |  | 
|  | 341 | /// Utility function to compute the size of the encoding. | 
|  | 342 | uint64_t MCDwarfLineAddr::ComputeSize(int64_t LineDelta, uint64_t AddrDelta) { | 
|  | 343 | SmallString<256> Tmp; | 
|  | 344 | raw_svector_ostream OS(Tmp); | 
|  | 345 | MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); | 
|  | 346 | return OS.GetNumBytesInBuffer(); | 
|  | 347 | } | 
|  | 348 |  | 
|  | 349 | /// Utility function to write the encoding to an object writer. | 
|  | 350 | void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta, | 
|  | 351 | uint64_t AddrDelta) { | 
|  | 352 | SmallString<256> Tmp; | 
|  | 353 | raw_svector_ostream OS(Tmp); | 
|  | 354 | MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); | 
|  | 355 | OW->WriteBytes(OS.str()); | 
|  | 356 | } | 
|  | 357 |  | 
|  | 358 | /// Utility function to emit the encoding to a streamer. | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame^] | 359 | void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 360 | uint64_t AddrDelta) { | 
|  | 361 | SmallString<256> Tmp; | 
|  | 362 | raw_svector_ostream OS(Tmp); | 
|  | 363 | MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); | 
|  | 364 | MCOS->EmitBytes(OS.str(), /*AddrSpace=*/0); | 
|  | 365 | } | 
|  | 366 |  | 
|  | 367 | /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. | 
|  | 368 | void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta, | 
|  | 369 | raw_ostream &OS) { | 
|  | 370 | uint64_t Temp, Opcode; | 
|  | 371 | bool NeedCopy = false; | 
|  | 372 |  | 
|  | 373 | // Scale the address delta by the minimum instruction length. | 
|  | 374 | AddrDelta = ScaleAddrDelta(AddrDelta); | 
|  | 375 |  | 
|  | 376 | // A LineDelta of INT64_MAX is a signal that this is actually a | 
|  | 377 | // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the | 
|  | 378 | // end_sequence to emit the matrix entry. | 
|  | 379 | if (LineDelta == INT64_MAX) { | 
|  | 380 | if (AddrDelta == MAX_SPECIAL_ADDR_DELTA) | 
|  | 381 | OS << char(dwarf::DW_LNS_const_add_pc); | 
|  | 382 | else { | 
|  | 383 | OS << char(dwarf::DW_LNS_advance_pc); | 
|  | 384 | SmallString<32> Tmp; | 
|  | 385 | raw_svector_ostream OSE(Tmp); | 
|  | 386 | MCObjectWriter::EncodeULEB128(AddrDelta, OSE); | 
|  | 387 | OS << OSE.str(); | 
|  | 388 | } | 
|  | 389 | OS << char(dwarf::DW_LNS_extended_op); | 
|  | 390 | OS << char(1); | 
|  | 391 | OS << char(dwarf::DW_LNE_end_sequence); | 
|  | 392 | return; | 
|  | 393 | } | 
|  | 394 |  | 
|  | 395 | // Bias the line delta by the base. | 
|  | 396 | Temp = LineDelta - DWARF2_LINE_BASE; | 
|  | 397 |  | 
|  | 398 | // If the line increment is out of range of a special opcode, we must encode | 
|  | 399 | // it with DW_LNS_advance_line. | 
|  | 400 | if (Temp >= DWARF2_LINE_RANGE) { | 
|  | 401 | OS << char(dwarf::DW_LNS_advance_line); | 
|  | 402 | SmallString<32> Tmp; | 
|  | 403 | raw_svector_ostream OSE(Tmp); | 
|  | 404 | MCObjectWriter::EncodeSLEB128(LineDelta, OSE); | 
|  | 405 | OS << OSE.str(); | 
|  | 406 |  | 
|  | 407 | LineDelta = 0; | 
|  | 408 | Temp = 0 - DWARF2_LINE_BASE; | 
|  | 409 | NeedCopy = true; | 
|  | 410 | } | 
|  | 411 |  | 
|  | 412 | // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode. | 
|  | 413 | if (LineDelta == 0 && AddrDelta == 0) { | 
|  | 414 | OS << char(dwarf::DW_LNS_copy); | 
|  | 415 | return; | 
|  | 416 | } | 
|  | 417 |  | 
|  | 418 | // Bias the opcode by the special opcode base. | 
|  | 419 | Temp += DWARF2_LINE_OPCODE_BASE; | 
|  | 420 |  | 
|  | 421 | // Avoid overflow when addr_delta is large. | 
|  | 422 | if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) { | 
|  | 423 | // Try using a special opcode. | 
|  | 424 | Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE; | 
|  | 425 | if (Opcode <= 255) { | 
|  | 426 | OS << char(Opcode); | 
|  | 427 | return; | 
|  | 428 | } | 
|  | 429 |  | 
|  | 430 | // Try using DW_LNS_const_add_pc followed by special op. | 
|  | 431 | Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; | 
|  | 432 | if (Opcode <= 255) { | 
|  | 433 | OS << char(dwarf::DW_LNS_const_add_pc); | 
|  | 434 | OS << char(Opcode); | 
|  | 435 | return; | 
|  | 436 | } | 
|  | 437 | } | 
|  | 438 |  | 
|  | 439 | // Otherwise use DW_LNS_advance_pc. | 
|  | 440 | OS << char(dwarf::DW_LNS_advance_pc); | 
|  | 441 | SmallString<32> Tmp; | 
|  | 442 | raw_svector_ostream OSE(Tmp); | 
|  | 443 | MCObjectWriter::EncodeULEB128(AddrDelta, OSE); | 
|  | 444 | OS << OSE.str(); | 
|  | 445 |  | 
|  | 446 | if (NeedCopy) | 
|  | 447 | OS << char(dwarf::DW_LNS_copy); | 
|  | 448 | else | 
|  | 449 | OS << char(Temp); | 
|  | 450 | } | 
|  | 451 |  | 
| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 452 | void MCDwarfFile::print(raw_ostream &OS) const { | 
|  | 453 | OS << '"' << getName() << '"'; | 
|  | 454 | } | 
|  | 455 |  | 
|  | 456 | void MCDwarfFile::dump() const { | 
|  | 457 | print(dbgs()); | 
|  | 458 | } | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 459 |  |