| 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 |  | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 10 | #include "llvm/ADT/FoldingSet.h" | 
| Rafael Espindola | 767b1be | 2010-12-04 00:31:13 +0000 | [diff] [blame] | 11 | #include "llvm/MC/MCAsmInfo.h" | 
| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 12 | #include "llvm/MC/MCDwarf.h" | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 13 | #include "llvm/MC/MCAssembler.h" | 
| Rafael Espindola | ad8aaa0 | 2010-11-22 11:53:17 +0000 | [diff] [blame] | 14 | #include "llvm/MC/MCStreamer.h" | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 15 | #include "llvm/MC/MCSymbol.h" | 
|  | 16 | #include "llvm/MC/MCExpr.h" | 
|  | 17 | #include "llvm/MC/MCContext.h" | 
|  | 18 | #include "llvm/MC/MCObjectWriter.h" | 
|  | 19 | #include "llvm/ADT/SmallString.h" | 
| Rafael Espindola | a8cfb87 | 2011-04-28 02:46:42 +0000 | [diff] [blame] | 20 | #include "llvm/ADT/Twine.h" | 
| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 21 | #include "llvm/Support/Debug.h" | 
| Rafael Espindola | fe024d0 | 2010-12-28 18:36:23 +0000 | [diff] [blame] | 22 | #include "llvm/Support/ErrorHandling.h" | 
| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 23 | #include "llvm/Support/raw_ostream.h" | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 24 | #include "llvm/Target/TargetAsmBackend.h" | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 25 | #include "llvm/Target/TargetAsmInfo.h" | 
| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 26 | using namespace llvm; | 
|  | 27 |  | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 28 | // Given a special op, return the address skip amount (in units of | 
|  | 29 | // DWARF2_LINE_MIN_INSN_LENGTH. | 
|  | 30 | #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) | 
|  | 31 |  | 
|  | 32 | // The maximum address skip amount that can be encoded with a special op. | 
|  | 33 | #define MAX_SPECIAL_ADDR_DELTA		SPECIAL_ADDR(255) | 
|  | 34 |  | 
|  | 35 | // First special line opcode - leave room for the standard opcodes. | 
|  | 36 | // Note: If you want to change this, you'll have to update the | 
|  | 37 | // "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit(). | 
|  | 38 | #define DWARF2_LINE_OPCODE_BASE		13 | 
|  | 39 |  | 
|  | 40 | // Minimum line offset in a special line info. opcode.  This value | 
|  | 41 | // was chosen to give a reasonable range of values. | 
|  | 42 | #define DWARF2_LINE_BASE		-5 | 
|  | 43 |  | 
|  | 44 | // Range of line offsets in a special line info. opcode. | 
|  | 45 | # define DWARF2_LINE_RANGE		14 | 
|  | 46 |  | 
|  | 47 | // Define the architecture-dependent minimum instruction length (in bytes). | 
|  | 48 | // This value should be rather too small than too big. | 
|  | 49 | # define DWARF2_LINE_MIN_INSN_LENGTH	1 | 
|  | 50 |  | 
|  | 51 | // Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting, | 
|  | 52 | // this routine is a nop and will be optimized away. | 
|  | 53 | static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) | 
|  | 54 | { | 
|  | 55 | if (DWARF2_LINE_MIN_INSN_LENGTH == 1) | 
|  | 56 | return AddrDelta; | 
|  | 57 | if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) { | 
|  | 58 | // TODO: report this error, but really only once. | 
|  | 59 | ; | 
|  | 60 | } | 
|  | 61 | return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH; | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | // | 
|  | 65 | // This is called when an instruction is assembled into the specified section | 
|  | 66 | // and if there is information from the last .loc directive that has yet to have | 
|  | 67 | // a line entry made for it is made. | 
|  | 68 | // | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame] | 69 | void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) { | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 70 | if (!MCOS->getContext().getDwarfLocSeen()) | 
|  | 71 | return; | 
|  | 72 |  | 
|  | 73 | // Create a symbol at in the current section for use in the line entry. | 
|  | 74 | MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol(); | 
|  | 75 | // Set the value of the symbol to use for the MCLineEntry. | 
|  | 76 | MCOS->EmitLabel(LineSym); | 
|  | 77 |  | 
|  | 78 | // Get the current .loc info saved in the context. | 
|  | 79 | const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc(); | 
|  | 80 |  | 
|  | 81 | // Create a (local) line entry with the symbol and the current .loc info. | 
|  | 82 | MCLineEntry LineEntry(LineSym, DwarfLoc); | 
|  | 83 |  | 
|  | 84 | // clear DwarfLocSeen saying the current .loc info is now used. | 
| Kevin Enderby | 3f55c24 | 2010-10-04 20:17:24 +0000 | [diff] [blame] | 85 | MCOS->getContext().ClearDwarfLocSeen(); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 86 |  | 
|  | 87 | // Get the MCLineSection for this section, if one does not exist for this | 
|  | 88 | // section create it. | 
| Rafael Espindola | 17fd7bd | 2010-11-19 07:41:23 +0000 | [diff] [blame] | 89 | const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 90 | MCOS->getContext().getMCLineSections(); | 
| Rafael Espindola | 17fd7bd | 2010-11-19 07:41:23 +0000 | [diff] [blame] | 91 | MCLineSection *LineSection = MCLineSections.lookup(Section); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 92 | if (!LineSection) { | 
|  | 93 | // Create a new MCLineSection.  This will be deleted after the dwarf line | 
|  | 94 | // table is created using it by iterating through the MCLineSections | 
|  | 95 | // DenseMap. | 
|  | 96 | LineSection = new MCLineSection; | 
|  | 97 | // Save a pointer to the new LineSection into the MCLineSections DenseMap. | 
| Rafael Espindola | 17fd7bd | 2010-11-19 07:41:23 +0000 | [diff] [blame] | 98 | MCOS->getContext().addMCLineSection(Section, LineSection); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 99 | } | 
|  | 100 |  | 
|  | 101 | // Add the line entry to this section's entries. | 
|  | 102 | LineSection->addLineEntry(LineEntry); | 
|  | 103 | } | 
|  | 104 |  | 
|  | 105 | // | 
|  | 106 | // This helper routine returns an expression of End - Start + IntVal . | 
|  | 107 | // | 
| Rafael Espindola | 5fad7a9 | 2010-12-09 23:08:35 +0000 | [diff] [blame] | 108 | static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, | 
|  | 109 | const MCSymbol &Start, | 
|  | 110 | const MCSymbol &End, | 
|  | 111 | int IntVal) { | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 112 | MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; | 
|  | 113 | const MCExpr *Res = | 
| Rafael Espindola | 5fad7a9 | 2010-12-09 23:08:35 +0000 | [diff] [blame] | 114 | MCSymbolRefExpr::Create(&End, Variant, MCOS.getContext()); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 115 | const MCExpr *RHS = | 
| Rafael Espindola | 5fad7a9 | 2010-12-09 23:08:35 +0000 | [diff] [blame] | 116 | MCSymbolRefExpr::Create(&Start, Variant, MCOS.getContext()); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 117 | const MCExpr *Res1 = | 
| Rafael Espindola | 5fad7a9 | 2010-12-09 23:08:35 +0000 | [diff] [blame] | 118 | MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext()); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 119 | const MCExpr *Res2 = | 
| Rafael Espindola | 5fad7a9 | 2010-12-09 23:08:35 +0000 | [diff] [blame] | 120 | MCConstantExpr::Create(IntVal, MCOS.getContext()); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 121 | const MCExpr *Res3 = | 
| Rafael Espindola | 5fad7a9 | 2010-12-09 23:08:35 +0000 | [diff] [blame] | 122 | MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext()); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 123 | return Res3; | 
|  | 124 | } | 
|  | 125 |  | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 126 | // | 
|  | 127 | // This emits the Dwarf line table for the specified section from the entries | 
|  | 128 | // in the LineSection. | 
|  | 129 | // | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame] | 130 | static inline void EmitDwarfLineTable(MCStreamer *MCOS, | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 131 | const MCSection *Section, | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 132 | const MCLineSection *LineSection) { | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 133 | unsigned FileNum = 1; | 
|  | 134 | unsigned LastLine = 1; | 
|  | 135 | unsigned Column = 0; | 
|  | 136 | unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; | 
|  | 137 | unsigned Isa = 0; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 138 | MCSymbol *LastLabel = NULL; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 139 |  | 
|  | 140 | // Loop through each MCLineEntry and encode the dwarf line number table. | 
| Rafael Espindola | 17fd7bd | 2010-11-19 07:41:23 +0000 | [diff] [blame] | 141 | for (MCLineSection::const_iterator | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 142 | it = LineSection->getMCLineEntries()->begin(), | 
|  | 143 | ie = LineSection->getMCLineEntries()->end(); it != ie; ++it) { | 
|  | 144 |  | 
|  | 145 | if (FileNum != it->getFileNum()) { | 
|  | 146 | FileNum = it->getFileNum(); | 
|  | 147 | MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1); | 
| Rafael Espindola | 3ff5709 | 2010-11-02 17:22:24 +0000 | [diff] [blame] | 148 | MCOS->EmitULEB128IntValue(FileNum); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 149 | } | 
|  | 150 | if (Column != it->getColumn()) { | 
|  | 151 | Column = it->getColumn(); | 
|  | 152 | MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); | 
| Rafael Espindola | 3ff5709 | 2010-11-02 17:22:24 +0000 | [diff] [blame] | 153 | MCOS->EmitULEB128IntValue(Column); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 154 | } | 
|  | 155 | if (Isa != it->getIsa()) { | 
|  | 156 | Isa = it->getIsa(); | 
|  | 157 | MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); | 
| Rafael Espindola | 3ff5709 | 2010-11-02 17:22:24 +0000 | [diff] [blame] | 158 | MCOS->EmitULEB128IntValue(Isa); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 159 | } | 
|  | 160 | if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { | 
|  | 161 | Flags = it->getFlags(); | 
|  | 162 | MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); | 
|  | 163 | } | 
|  | 164 | if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK) | 
|  | 165 | MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); | 
|  | 166 | if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END) | 
|  | 167 | MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); | 
|  | 168 | if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) | 
|  | 169 | MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); | 
|  | 170 |  | 
| Rafael Espindola | 64185cc | 2010-11-13 01:06:27 +0000 | [diff] [blame] | 171 | int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 172 | MCSymbol *Label = it->getLabel(); | 
|  | 173 |  | 
|  | 174 | // At this point we want to emit/create the sequence to encode the delta in | 
|  | 175 | // line numbers and the increment of the address from the previous Label | 
|  | 176 | // and the current Label. | 
| Rafael Espindola | 32a006e | 2010-12-03 00:55:40 +0000 | [diff] [blame] | 177 | MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 178 |  | 
|  | 179 | LastLine = it->getLine(); | 
|  | 180 | LastLabel = Label; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 181 | } | 
|  | 182 |  | 
|  | 183 | // Emit a DW_LNE_end_sequence for the end of the section. | 
|  | 184 | // Using the pointer Section create a temporary label at the end of the | 
|  | 185 | // section and use that and the LastLabel to compute the address delta | 
|  | 186 | // and use INT64_MAX as the line delta which is the signal that this is | 
|  | 187 | // actually a DW_LNE_end_sequence. | 
|  | 188 |  | 
|  | 189 | // Switch to the section to be able to create a symbol at its end. | 
|  | 190 | MCOS->SwitchSection(Section); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 191 |  | 
|  | 192 | MCContext &context = MCOS->getContext(); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 193 | // Create a symbol at the end of the section. | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 194 | MCSymbol *SectionEnd = context.CreateTempSymbol(); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 195 | // Set the value of the symbol, as we are at the end of the section. | 
|  | 196 | MCOS->EmitLabel(SectionEnd); | 
|  | 197 |  | 
|  | 198 | // Switch back the the dwarf line section. | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 199 | MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection()); | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame] | 200 |  | 
| Rafael Espindola | 32a006e | 2010-12-03 00:55:40 +0000 | [diff] [blame] | 201 | MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 202 | } | 
|  | 203 |  | 
|  | 204 | // | 
|  | 205 | // This emits the Dwarf file and the line tables. | 
|  | 206 | // | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 207 | void MCDwarfFileTable::Emit(MCStreamer *MCOS) { | 
|  | 208 | MCContext &context = MCOS->getContext(); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 209 | // Switch to the section where the table will be emitted into. | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 210 | MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection()); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 211 |  | 
|  | 212 | // Create a symbol at the beginning of this section. | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 213 | MCSymbol *LineStartSym = context.CreateTempSymbol(); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 214 | // Set the value of the symbol, as we are at the start of the section. | 
|  | 215 | MCOS->EmitLabel(LineStartSym); | 
|  | 216 |  | 
|  | 217 | // Create a symbol for the end of the section (to be set when we get there). | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 218 | MCSymbol *LineEndSym = context.CreateTempSymbol(); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 219 |  | 
|  | 220 | // The first 4 bytes is the total length of the information for this | 
|  | 221 | // compilation unit (not including these 4 bytes for the length). | 
| Rafael Espindola | 5fad7a9 | 2010-12-09 23:08:35 +0000 | [diff] [blame] | 222 | MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym,4), | 
| Rafael Espindola | 0bbe0b4 | 2010-12-06 17:27:56 +0000 | [diff] [blame] | 223 | 4); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 224 |  | 
|  | 225 | // Next 2 bytes is the Version, which is Dwarf 2. | 
|  | 226 | MCOS->EmitIntValue(2, 2); | 
|  | 227 |  | 
|  | 228 | // Create a symbol for the end of the prologue (to be set when we get there). | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 229 | MCSymbol *ProEndSym = context.CreateTempSymbol(); // Lprologue_end | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 230 |  | 
|  | 231 | // Length of the prologue, is the next 4 bytes.  Which is the start of the | 
|  | 232 | // section to the end of the prologue.  Not including the 4 bytes for the | 
|  | 233 | // total length, the 2 bytes for the version, and these 4 bytes for the | 
|  | 234 | // length of the prologue. | 
| Rafael Espindola | 5fad7a9 | 2010-12-09 23:08:35 +0000 | [diff] [blame] | 235 | MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 236 | (4 + 2 + 4)), | 
| Rafael Espindola | 5d4918d | 2010-12-04 03:21:47 +0000 | [diff] [blame] | 237 | 4, 0); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 238 |  | 
|  | 239 | // Parameters of the state machine, are next. | 
|  | 240 | MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); | 
|  | 241 | MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); | 
|  | 242 | MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); | 
|  | 243 | MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); | 
|  | 244 | MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1); | 
|  | 245 |  | 
|  | 246 | // Standard opcode lengths | 
|  | 247 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy | 
|  | 248 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc | 
|  | 249 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line | 
|  | 250 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file | 
|  | 251 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column | 
|  | 252 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt | 
|  | 253 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block | 
|  | 254 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc | 
|  | 255 | MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc | 
|  | 256 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end | 
|  | 257 | MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin | 
|  | 258 | MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa | 
|  | 259 |  | 
|  | 260 | // Put out the directory and file tables. | 
|  | 261 |  | 
|  | 262 | // First the directory table. | 
|  | 263 | const std::vector<StringRef> &MCDwarfDirs = | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 264 | context.getMCDwarfDirs(); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 265 | for (unsigned i = 0; i < MCDwarfDirs.size(); i++) { | 
|  | 266 | MCOS->EmitBytes(MCDwarfDirs[i], 0); // the DirectoryName | 
|  | 267 | MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string | 
|  | 268 | } | 
|  | 269 | MCOS->EmitIntValue(0, 1); // Terminate the directory list | 
|  | 270 |  | 
|  | 271 | // Second the file table. | 
|  | 272 | const std::vector<MCDwarfFile *> &MCDwarfFiles = | 
|  | 273 | MCOS->getContext().getMCDwarfFiles(); | 
|  | 274 | for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { | 
|  | 275 | MCOS->EmitBytes(MCDwarfFiles[i]->getName(), 0); // FileName | 
|  | 276 | MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string | 
| Rafael Espindola | 3ff5709 | 2010-11-02 17:22:24 +0000 | [diff] [blame] | 277 | // the Directory num | 
|  | 278 | MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex()); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 279 | MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0) | 
|  | 280 | MCOS->EmitIntValue(0, 1); // filesize (always 0) | 
|  | 281 | } | 
|  | 282 | MCOS->EmitIntValue(0, 1); // Terminate the file list | 
|  | 283 |  | 
|  | 284 | // This is the end of the prologue, so set the value of the symbol at the | 
|  | 285 | // end of the prologue (that was used in a previous expression). | 
|  | 286 | MCOS->EmitLabel(ProEndSym); | 
|  | 287 |  | 
|  | 288 | // Put out the line tables. | 
| Rafael Espindola | 17fd7bd | 2010-11-19 07:41:23 +0000 | [diff] [blame] | 289 | const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 290 | MCOS->getContext().getMCLineSections(); | 
| Rafael Espindola | 17fd7bd | 2010-11-19 07:41:23 +0000 | [diff] [blame] | 291 | const std::vector<const MCSection *> &MCLineSectionOrder = | 
|  | 292 | MCOS->getContext().getMCLineSectionOrder(); | 
|  | 293 | for (std::vector<const MCSection*>::const_iterator it = | 
|  | 294 | MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie; | 
|  | 295 | ++it) { | 
|  | 296 | const MCSection *Sec = *it; | 
|  | 297 | const MCLineSection *Line = MCLineSections.lookup(Sec); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 298 | EmitDwarfLineTable(MCOS, Sec, Line); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 299 |  | 
|  | 300 | // Now delete the MCLineSections that were created in MCLineEntry::Make() | 
|  | 301 | // and used to emit the line table. | 
| Rafael Espindola | 17fd7bd | 2010-11-19 07:41:23 +0000 | [diff] [blame] | 302 | delete Line; | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 303 | } | 
|  | 304 |  | 
| Rafael Espindola | 767b1be | 2010-12-04 00:31:13 +0000 | [diff] [blame] | 305 | if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines() | 
|  | 306 | && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) { | 
| Rafael Espindola | a8de83c | 2010-12-03 23:36:59 +0000 | [diff] [blame] | 307 | // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures | 
|  | 308 | // it requires: | 
|  | 309 | // total_length >= prologue_length + 10 | 
|  | 310 | // We are 4 bytes short, since we have total_length = 51 and | 
|  | 311 | // prologue_length = 45 | 
| Devang Patel | 5113cdb | 2010-12-03 00:10:48 +0000 | [diff] [blame] | 312 |  | 
| Rafael Espindola | a8de83c | 2010-12-03 23:36:59 +0000 | [diff] [blame] | 313 | // The regular end_sequence should be sufficient. | 
|  | 314 | MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0); | 
| Devang Patel | 5113cdb | 2010-12-03 00:10:48 +0000 | [diff] [blame] | 315 | } | 
|  | 316 |  | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 317 | // This is the end of the section, so set the value of the symbol at the end | 
|  | 318 | // of this section (that was used in a previous expression). | 
|  | 319 | MCOS->EmitLabel(LineEndSym); | 
|  | 320 | } | 
|  | 321 |  | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 322 | /// Utility function to write the encoding to an object writer. | 
|  | 323 | void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta, | 
|  | 324 | uint64_t AddrDelta) { | 
|  | 325 | SmallString<256> Tmp; | 
|  | 326 | raw_svector_ostream OS(Tmp); | 
|  | 327 | MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); | 
|  | 328 | OW->WriteBytes(OS.str()); | 
|  | 329 | } | 
|  | 330 |  | 
|  | 331 | /// Utility function to emit the encoding to a streamer. | 
| Rafael Espindola | 195a0ce | 2010-11-19 02:26:16 +0000 | [diff] [blame] | 332 | void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 333 | uint64_t AddrDelta) { | 
|  | 334 | SmallString<256> Tmp; | 
|  | 335 | raw_svector_ostream OS(Tmp); | 
|  | 336 | MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); | 
|  | 337 | MCOS->EmitBytes(OS.str(), /*AddrSpace=*/0); | 
|  | 338 | } | 
|  | 339 |  | 
|  | 340 | /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. | 
|  | 341 | void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta, | 
|  | 342 | raw_ostream &OS) { | 
|  | 343 | uint64_t Temp, Opcode; | 
|  | 344 | bool NeedCopy = false; | 
|  | 345 |  | 
|  | 346 | // Scale the address delta by the minimum instruction length. | 
|  | 347 | AddrDelta = ScaleAddrDelta(AddrDelta); | 
|  | 348 |  | 
|  | 349 | // A LineDelta of INT64_MAX is a signal that this is actually a | 
|  | 350 | // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the | 
|  | 351 | // end_sequence to emit the matrix entry. | 
|  | 352 | if (LineDelta == INT64_MAX) { | 
|  | 353 | if (AddrDelta == MAX_SPECIAL_ADDR_DELTA) | 
|  | 354 | OS << char(dwarf::DW_LNS_const_add_pc); | 
|  | 355 | else { | 
|  | 356 | OS << char(dwarf::DW_LNS_advance_pc); | 
| Benjamin Kramer | dcf0e0c | 2011-06-18 14:42:47 +0000 | [diff] [blame] | 357 | MCObjectWriter::EncodeULEB128(AddrDelta, OS); | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 358 | } | 
|  | 359 | OS << char(dwarf::DW_LNS_extended_op); | 
|  | 360 | OS << char(1); | 
|  | 361 | OS << char(dwarf::DW_LNE_end_sequence); | 
|  | 362 | return; | 
|  | 363 | } | 
|  | 364 |  | 
|  | 365 | // Bias the line delta by the base. | 
|  | 366 | Temp = LineDelta - DWARF2_LINE_BASE; | 
|  | 367 |  | 
|  | 368 | // If the line increment is out of range of a special opcode, we must encode | 
|  | 369 | // it with DW_LNS_advance_line. | 
|  | 370 | if (Temp >= DWARF2_LINE_RANGE) { | 
|  | 371 | OS << char(dwarf::DW_LNS_advance_line); | 
|  | 372 | SmallString<32> Tmp; | 
|  | 373 | raw_svector_ostream OSE(Tmp); | 
|  | 374 | MCObjectWriter::EncodeSLEB128(LineDelta, OSE); | 
|  | 375 | OS << OSE.str(); | 
|  | 376 |  | 
|  | 377 | LineDelta = 0; | 
|  | 378 | Temp = 0 - DWARF2_LINE_BASE; | 
|  | 379 | NeedCopy = true; | 
|  | 380 | } | 
|  | 381 |  | 
|  | 382 | // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode. | 
|  | 383 | if (LineDelta == 0 && AddrDelta == 0) { | 
|  | 384 | OS << char(dwarf::DW_LNS_copy); | 
|  | 385 | return; | 
|  | 386 | } | 
|  | 387 |  | 
|  | 388 | // Bias the opcode by the special opcode base. | 
|  | 389 | Temp += DWARF2_LINE_OPCODE_BASE; | 
|  | 390 |  | 
|  | 391 | // Avoid overflow when addr_delta is large. | 
|  | 392 | if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) { | 
|  | 393 | // Try using a special opcode. | 
|  | 394 | Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE; | 
|  | 395 | if (Opcode <= 255) { | 
|  | 396 | OS << char(Opcode); | 
|  | 397 | return; | 
|  | 398 | } | 
|  | 399 |  | 
|  | 400 | // Try using DW_LNS_const_add_pc followed by special op. | 
|  | 401 | Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; | 
|  | 402 | if (Opcode <= 255) { | 
|  | 403 | OS << char(dwarf::DW_LNS_const_add_pc); | 
|  | 404 | OS << char(Opcode); | 
|  | 405 | return; | 
|  | 406 | } | 
|  | 407 | } | 
|  | 408 |  | 
|  | 409 | // Otherwise use DW_LNS_advance_pc. | 
|  | 410 | OS << char(dwarf::DW_LNS_advance_pc); | 
|  | 411 | SmallString<32> Tmp; | 
|  | 412 | raw_svector_ostream OSE(Tmp); | 
|  | 413 | MCObjectWriter::EncodeULEB128(AddrDelta, OSE); | 
|  | 414 | OS << OSE.str(); | 
|  | 415 |  | 
|  | 416 | if (NeedCopy) | 
|  | 417 | OS << char(dwarf::DW_LNS_copy); | 
|  | 418 | else | 
|  | 419 | OS << char(Temp); | 
|  | 420 | } | 
|  | 421 |  | 
| Kevin Enderby | 7cbf73a | 2010-07-28 20:55:35 +0000 | [diff] [blame] | 422 | void MCDwarfFile::print(raw_ostream &OS) const { | 
|  | 423 | OS << '"' << getName() << '"'; | 
|  | 424 | } | 
|  | 425 |  | 
|  | 426 | void MCDwarfFile::dump() const { | 
|  | 427 | print(dbgs()); | 
|  | 428 | } | 
| Kevin Enderby | c095793 | 2010-09-30 16:52:03 +0000 | [diff] [blame] | 429 |  | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 430 | static int getDataAlignmentFactor(MCStreamer &streamer) { | 
|  | 431 | MCContext &context = streamer.getContext(); | 
|  | 432 | const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); | 
|  | 433 | int size = asmInfo.getPointerSize(); | 
| Anton Korobeynikov | 16c29b5 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 434 | if (asmInfo.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp) | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 435 | return size; | 
|  | 436 | else | 
|  | 437 | return -size; | 
|  | 438 | } | 
|  | 439 |  | 
| Rafael Espindola | abf9af6 | 2011-04-22 00:08:43 +0000 | [diff] [blame] | 440 | static unsigned getSizeForEncoding(MCStreamer &streamer, | 
|  | 441 | unsigned symbolEncoding) { | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 442 | MCContext &context = streamer.getContext(); | 
|  | 443 | const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); | 
|  | 444 | unsigned format = symbolEncoding & 0x0f; | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 445 | switch (format) { | 
|  | 446 | default: | 
|  | 447 | assert(0 && "Unknown Encoding"); | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 448 | case dwarf::DW_EH_PE_absptr: | 
|  | 449 | case dwarf::DW_EH_PE_signed: | 
| Rafael Espindola | abf9af6 | 2011-04-22 00:08:43 +0000 | [diff] [blame] | 450 | return asmInfo.getPointerSize(); | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 451 | case dwarf::DW_EH_PE_udata2: | 
|  | 452 | case dwarf::DW_EH_PE_sdata2: | 
| Rafael Espindola | abf9af6 | 2011-04-22 00:08:43 +0000 | [diff] [blame] | 453 | return 2; | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 454 | case dwarf::DW_EH_PE_udata4: | 
|  | 455 | case dwarf::DW_EH_PE_sdata4: | 
| Rafael Espindola | abf9af6 | 2011-04-22 00:08:43 +0000 | [diff] [blame] | 456 | return 4; | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 457 | case dwarf::DW_EH_PE_udata8: | 
|  | 458 | case dwarf::DW_EH_PE_sdata8: | 
| Rafael Espindola | abf9af6 | 2011-04-22 00:08:43 +0000 | [diff] [blame] | 459 | return 8; | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 460 | } | 
| Rafael Espindola | abf9af6 | 2011-04-22 00:08:43 +0000 | [diff] [blame] | 461 | } | 
|  | 462 |  | 
|  | 463 | static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, | 
|  | 464 | unsigned symbolEncoding) { | 
| Rafael Espindola | a0057ca | 2011-04-28 21:04:39 +0000 | [diff] [blame] | 465 | MCContext &context = streamer.getContext(); | 
|  | 466 | const MCAsmInfo &asmInfo = context.getAsmInfo(); | 
|  | 467 | const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol, | 
| Rafael Espindola | debd7e4 | 2011-05-01 03:50:49 +0000 | [diff] [blame] | 468 | symbolEncoding, | 
| Rafael Espindola | a0057ca | 2011-04-28 21:04:39 +0000 | [diff] [blame] | 469 | streamer); | 
| Rafael Espindola | abf9af6 | 2011-04-22 00:08:43 +0000 | [diff] [blame] | 470 | unsigned size = getSizeForEncoding(streamer, symbolEncoding); | 
| Rafael Espindola | debd7e4 | 2011-05-01 03:50:49 +0000 | [diff] [blame] | 471 | streamer.EmitAbsValue(v, size); | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 472 | } | 
|  | 473 |  | 
| Rafael Espindola | bfa27cc | 2011-04-28 16:09:09 +0000 | [diff] [blame] | 474 | static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, | 
|  | 475 | unsigned symbolEncoding) { | 
|  | 476 | MCContext &context = streamer.getContext(); | 
|  | 477 | const MCAsmInfo &asmInfo = context.getAsmInfo(); | 
| Rafael Espindola | debd7e4 | 2011-05-01 03:50:49 +0000 | [diff] [blame] | 478 | const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol, | 
|  | 479 | symbolEncoding, | 
|  | 480 | streamer); | 
| Rafael Espindola | bfa27cc | 2011-04-28 16:09:09 +0000 | [diff] [blame] | 481 | unsigned size = getSizeForEncoding(streamer, symbolEncoding); | 
| Rafael Espindola | debd7e4 | 2011-05-01 03:50:49 +0000 | [diff] [blame] | 482 | streamer.EmitValue(v, size); | 
| Rafael Espindola | bfa27cc | 2011-04-28 16:09:09 +0000 | [diff] [blame] | 483 | } | 
|  | 484 |  | 
| Rafael Espindola | b40a71f | 2010-12-29 01:42:56 +0000 | [diff] [blame] | 485 | static const MachineLocation TranslateMachineLocation( | 
|  | 486 | const TargetAsmInfo &AsmInfo, | 
|  | 487 | const MachineLocation &Loc) { | 
|  | 488 | unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? | 
|  | 489 | MachineLocation::VirtualFP : | 
|  | 490 | unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true)); | 
|  | 491 | const MachineLocation &NewLoc = Loc.isReg() ? | 
|  | 492 | MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); | 
|  | 493 | return NewLoc; | 
|  | 494 | } | 
|  | 495 |  | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 496 | namespace { | 
|  | 497 | class FrameEmitterImpl { | 
|  | 498 | int CFAOffset; | 
| Rafael Espindola | 514cecc | 2011-04-28 03:26:11 +0000 | [diff] [blame] | 499 | int CIENum; | 
| Rafael Espindola | 5426a9e | 2011-05-01 04:49:54 +0000 | [diff] [blame] | 500 | bool UsingCFI; | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 501 | bool IsEH; | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 502 | const MCSymbol *SectionStart; | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 503 |  | 
|  | 504 | public: | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 505 | FrameEmitterImpl(bool usingCFI, bool isEH, const MCSymbol *sectionStart) : | 
|  | 506 | CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH), | 
|  | 507 | SectionStart(sectionStart) { | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 508 | } | 
|  | 509 |  | 
| Bill Wendling | e3cd13f | 2011-06-23 01:06:23 +0000 | [diff] [blame^] | 510 | /// EmitCompactUnwind - Emit the unwind information in a compact way. If | 
|  | 511 | /// we're successful, return 'true'. Otherwise, return 'false' and it will | 
|  | 512 | /// emit the normal CIE and FDE. | 
|  | 513 | bool EmitCompactUnwind(MCStreamer &streamer, | 
|  | 514 | const MCDwarfFrameInfo &frame); | 
|  | 515 |  | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 516 | const MCSymbol &EmitCIE(MCStreamer &streamer, | 
|  | 517 | const MCSymbol *personality, | 
|  | 518 | unsigned personalityEncoding, | 
|  | 519 | const MCSymbol *lsda, | 
|  | 520 | unsigned lsdaEncoding); | 
|  | 521 | MCSymbol *EmitFDE(MCStreamer &streamer, | 
|  | 522 | const MCSymbol &cieStart, | 
| Rafael Espindola | 9f270da | 2011-05-10 03:01:39 +0000 | [diff] [blame] | 523 | const MCDwarfFrameInfo &frame); | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 524 | void EmitCFIInstructions(MCStreamer &streamer, | 
|  | 525 | const std::vector<MCCFIInstruction> &Instrs, | 
|  | 526 | MCSymbol *BaseLabel); | 
|  | 527 | void EmitCFIInstruction(MCStreamer &Streamer, | 
|  | 528 | const MCCFIInstruction &Instr); | 
|  | 529 | }; | 
|  | 530 | } | 
|  | 531 |  | 
|  | 532 | void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, | 
|  | 533 | const MCCFIInstruction &Instr) { | 
|  | 534 | int dataAlignmentFactor = getDataAlignmentFactor(Streamer); | 
|  | 535 |  | 
|  | 536 | switch (Instr.getOperation()) { | 
|  | 537 | case MCCFIInstruction::Move: | 
|  | 538 | case MCCFIInstruction::RelMove: { | 
|  | 539 | const MachineLocation &Dst = Instr.getDestination(); | 
|  | 540 | const MachineLocation &Src = Instr.getSource(); | 
| Rafael Espindola | 5d7dcd3 | 2011-04-12 18:53:30 +0000 | [diff] [blame] | 541 | const bool IsRelative = Instr.getOperation() == MCCFIInstruction::RelMove; | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 542 |  | 
|  | 543 | // If advancing cfa. | 
|  | 544 | if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 545 | if (Src.getReg() == MachineLocation::VirtualFP) { | 
|  | 546 | Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); | 
|  | 547 | } else { | 
|  | 548 | Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); | 
|  | 549 | Streamer.EmitULEB128IntValue(Src.getReg()); | 
|  | 550 | } | 
|  | 551 |  | 
| Rafael Espindola | 5d7dcd3 | 2011-04-12 18:53:30 +0000 | [diff] [blame] | 552 | if (IsRelative) | 
|  | 553 | CFAOffset += Src.getOffset(); | 
|  | 554 | else | 
|  | 555 | CFAOffset = -Src.getOffset(); | 
|  | 556 |  | 
| Rafael Espindola | e8cfbd8 | 2011-04-21 23:39:26 +0000 | [diff] [blame] | 557 | Streamer.EmitULEB128IntValue(CFAOffset); | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 558 | return; | 
|  | 559 | } | 
|  | 560 |  | 
|  | 561 | if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { | 
|  | 562 | assert(Dst.isReg() && "Machine move not supported yet."); | 
|  | 563 | Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); | 
|  | 564 | Streamer.EmitULEB128IntValue(Dst.getReg()); | 
|  | 565 | return; | 
|  | 566 | } | 
|  | 567 |  | 
|  | 568 | unsigned Reg = Src.getReg(); | 
|  | 569 |  | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 570 | int Offset = Dst.getOffset(); | 
|  | 571 | if (IsRelative) | 
|  | 572 | Offset -= CFAOffset; | 
|  | 573 | Offset = Offset / dataAlignmentFactor; | 
|  | 574 |  | 
|  | 575 | if (Offset < 0) { | 
|  | 576 | Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); | 
|  | 577 | Streamer.EmitULEB128IntValue(Reg); | 
|  | 578 | Streamer.EmitSLEB128IntValue(Offset); | 
|  | 579 | } else if (Reg < 64) { | 
|  | 580 | Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); | 
| Rafael Espindola | eccbad7 | 2011-04-21 23:26:40 +0000 | [diff] [blame] | 581 | Streamer.EmitULEB128IntValue(Offset); | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 582 | } else { | 
|  | 583 | Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); | 
| Rafael Espindola | eccbad7 | 2011-04-21 23:26:40 +0000 | [diff] [blame] | 584 | Streamer.EmitULEB128IntValue(Reg); | 
|  | 585 | Streamer.EmitULEB128IntValue(Offset); | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 586 | } | 
|  | 587 | return; | 
|  | 588 | } | 
|  | 589 | case MCCFIInstruction::Remember: | 
|  | 590 | Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); | 
|  | 591 | return; | 
|  | 592 | case MCCFIInstruction::Restore: | 
|  | 593 | Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); | 
|  | 594 | return; | 
|  | 595 | case MCCFIInstruction::SameValue: { | 
|  | 596 | unsigned Reg = Instr.getDestination().getReg(); | 
|  | 597 | Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); | 
| Rafael Espindola | e8cfbd8 | 2011-04-21 23:39:26 +0000 | [diff] [blame] | 598 | Streamer.EmitULEB128IntValue(Reg); | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 599 | return; | 
|  | 600 | } | 
|  | 601 | } | 
|  | 602 | llvm_unreachable("Unhandled case in switch"); | 
|  | 603 | } | 
|  | 604 |  | 
|  | 605 | /// EmitFrameMoves - Emit frame instructions to describe the layout of the | 
|  | 606 | /// frame. | 
|  | 607 | void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, | 
|  | 608 | const std::vector<MCCFIInstruction> &Instrs, | 
|  | 609 | MCSymbol *BaseLabel) { | 
|  | 610 | for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { | 
|  | 611 | const MCCFIInstruction &Instr = Instrs[i]; | 
|  | 612 | MCSymbol *Label = Instr.getLabel(); | 
|  | 613 | // Throw out move if the label is invalid. | 
|  | 614 | if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. | 
|  | 615 |  | 
|  | 616 | // Advance row if new location. | 
|  | 617 | if (BaseLabel && Label) { | 
|  | 618 | MCSymbol *ThisSym = Label; | 
|  | 619 | if (ThisSym != BaseLabel) { | 
|  | 620 | streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); | 
|  | 621 | BaseLabel = ThisSym; | 
|  | 622 | } | 
|  | 623 | } | 
|  | 624 |  | 
|  | 625 | EmitCFIInstruction(streamer, Instr); | 
|  | 626 | } | 
|  | 627 | } | 
|  | 628 |  | 
| Bill Wendling | e3cd13f | 2011-06-23 01:06:23 +0000 | [diff] [blame^] | 629 | /// EmitCompactUnwind - Emit the unwind information in a compact way. If we're | 
|  | 630 | /// successful, return 'true'. Otherwise, return 'false' and it will emit the | 
|  | 631 | /// normal CIE and FDE. | 
|  | 632 | bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, | 
|  | 633 | const MCDwarfFrameInfo &Frame) { | 
|  | 634 | #if 1 | 
|  | 635 | return false; | 
|  | 636 | #else | 
|  | 637 | MCContext &Context = Streamer.getContext(); | 
|  | 638 | const TargetAsmInfo &TAI = Context.getTargetAsmInfo(); | 
|  | 639 | Streamer.SwitchSection(TAI.getCompactUnwindSection()); | 
|  | 640 |  | 
|  | 641 | unsigned FDEEncoding = TAI.getFDEEncoding(UsingCFI); | 
|  | 642 | unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); | 
|  | 643 |  | 
|  | 644 | // range-start range-length  compact-unwind-enc personality-func   lsda | 
|  | 645 | //  _foo       LfooEnd-_foo  0x00000023          0                 0 | 
|  | 646 | //  _bar       LbarEnd-_bar  0x00000025         __gxx_personality  except_tab1 | 
|  | 647 | // | 
|  | 648 | //   .section __LD,__compact_unwind,regular,debug | 
|  | 649 | // | 
|  | 650 | //   # compact unwind for _foo | 
|  | 651 | //   .quad _foo | 
|  | 652 | //   .set L1,LfooEnd-_foo | 
|  | 653 | //   .long L1 | 
|  | 654 | //   .long 0x01010001 | 
|  | 655 | //   .quad 0 | 
|  | 656 | //   .quad 0 | 
|  | 657 | // | 
|  | 658 | //   # compact unwind for _bar | 
|  | 659 | //   .quad _bar | 
|  | 660 | //   .set L2,LbarEnd-_bar | 
|  | 661 | //   .long L2 | 
|  | 662 | //   .long 0x01020011 | 
|  | 663 | //   .quad __gxx_personality | 
|  | 664 | //   .quad except_tab1 | 
|  | 665 |  | 
|  | 666 | // Range Start | 
|  | 667 | EmitSymbol(Streamer, *Frame.Begin, FDEEncoding); | 
|  | 668 |  | 
|  | 669 | // Range Length | 
|  | 670 | const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, | 
|  | 671 | *Frame.End, 0); | 
|  | 672 | Streamer.EmitAbsValue(Range, Size); | 
|  | 673 |  | 
|  | 674 | return true; | 
|  | 675 | #endif | 
|  | 676 | } | 
|  | 677 |  | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 678 | const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, | 
|  | 679 | const MCSymbol *personality, | 
|  | 680 | unsigned personalityEncoding, | 
|  | 681 | const MCSymbol *lsda, | 
|  | 682 | unsigned lsdaEncoding) { | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 683 | MCContext &context = streamer.getContext(); | 
|  | 684 | const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); | 
| Rafael Espindola | 514cecc | 2011-04-28 03:26:11 +0000 | [diff] [blame] | 685 |  | 
|  | 686 | MCSymbol *sectionStart; | 
| Rafael Espindola | 12f197b | 2011-05-10 19:51:53 +0000 | [diff] [blame] | 687 | if (asmInfo.isFunctionEHFrameSymbolPrivate() || !IsEH) | 
| Rafael Espindola | 514cecc | 2011-04-28 03:26:11 +0000 | [diff] [blame] | 688 | sectionStart = context.CreateTempSymbol(); | 
|  | 689 | else | 
|  | 690 | sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); | 
|  | 691 |  | 
|  | 692 | CIENum++; | 
|  | 693 |  | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 694 | MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol(); | 
|  | 695 |  | 
|  | 696 | // Length | 
|  | 697 | const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, | 
|  | 698 | *sectionEnd, 4); | 
|  | 699 | streamer.EmitLabel(sectionStart); | 
| Rafael Espindola | 9266cc4 | 2011-04-27 01:43:49 +0000 | [diff] [blame] | 700 | streamer.EmitAbsValue(Length, 4); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 701 |  | 
|  | 702 | // CIE ID | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 703 | unsigned CIE_ID = IsEH ? 0 : -1; | 
|  | 704 | streamer.EmitIntValue(CIE_ID, 4); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 705 |  | 
|  | 706 | // Version | 
|  | 707 | streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); | 
|  | 708 |  | 
|  | 709 | // Augmentation String | 
|  | 710 | SmallString<8> Augmentation; | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 711 | if (IsEH) { | 
|  | 712 | Augmentation += "z"; | 
|  | 713 | if (personality) | 
|  | 714 | Augmentation += "P"; | 
|  | 715 | if (lsda) | 
|  | 716 | Augmentation += "L"; | 
|  | 717 | Augmentation += "R"; | 
|  | 718 | streamer.EmitBytes(Augmentation.str(), 0); | 
|  | 719 | } | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 720 | streamer.EmitIntValue(0, 1); | 
|  | 721 |  | 
|  | 722 | // Code Alignment Factor | 
|  | 723 | streamer.EmitULEB128IntValue(1); | 
|  | 724 |  | 
|  | 725 | // Data Alignment Factor | 
|  | 726 | streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); | 
|  | 727 |  | 
|  | 728 | // Return Address Register | 
|  | 729 | streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(true)); | 
|  | 730 |  | 
|  | 731 | // Augmentation Data Length (optional) | 
| Rafael Espindola | 1f6c875 | 2011-04-29 21:50:57 +0000 | [diff] [blame] | 732 |  | 
|  | 733 | unsigned augmentationLength = 0; | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 734 | if (IsEH) { | 
|  | 735 | if (personality) { | 
|  | 736 | // Personality Encoding | 
|  | 737 | augmentationLength += 1; | 
|  | 738 | // Personality | 
|  | 739 | augmentationLength += getSizeForEncoding(streamer, personalityEncoding); | 
|  | 740 | } | 
|  | 741 | if (lsda) | 
|  | 742 | augmentationLength += 1; | 
|  | 743 | // Encoding of the FDE pointers | 
| Rafael Espindola | 1f6c875 | 2011-04-29 21:50:57 +0000 | [diff] [blame] | 744 | augmentationLength += 1; | 
| Rafael Espindola | 1f6c875 | 2011-04-29 21:50:57 +0000 | [diff] [blame] | 745 |  | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 746 | streamer.EmitULEB128IntValue(augmentationLength); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 747 |  | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 748 | // Augmentation Data (optional) | 
|  | 749 | if (personality) { | 
|  | 750 | // Personality Encoding | 
|  | 751 | streamer.EmitIntValue(personalityEncoding, 1); | 
|  | 752 | // Personality | 
|  | 753 | EmitPersonality(streamer, *personality, personalityEncoding); | 
|  | 754 | } | 
|  | 755 | if (lsda) | 
|  | 756 | streamer.EmitIntValue(lsdaEncoding, 1); // LSDA Encoding | 
|  | 757 | // Encoding of the FDE pointers | 
|  | 758 | streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1); | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 759 | } | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 760 |  | 
|  | 761 | // Initial Instructions | 
|  | 762 |  | 
|  | 763 | const std::vector<MachineMove> Moves = asmInfo.getInitialFrameState(); | 
| Rafael Espindola | fe024d0 | 2010-12-28 18:36:23 +0000 | [diff] [blame] | 764 | std::vector<MCCFIInstruction> Instructions; | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 765 |  | 
| Rafael Espindola | fe024d0 | 2010-12-28 18:36:23 +0000 | [diff] [blame] | 766 | for (int i = 0, n = Moves.size(); i != n; ++i) { | 
| Rafael Espindola | b40a71f | 2010-12-29 01:42:56 +0000 | [diff] [blame] | 767 | MCSymbol *Label = Moves[i].getLabel(); | 
|  | 768 | const MachineLocation &Dst = | 
|  | 769 | TranslateMachineLocation(asmInfo, Moves[i].getDestination()); | 
|  | 770 | const MachineLocation &Src = | 
|  | 771 | TranslateMachineLocation(asmInfo, Moves[i].getSource()); | 
|  | 772 | MCCFIInstruction Inst(Label, Dst, Src); | 
| Rafael Espindola | fe024d0 | 2010-12-28 18:36:23 +0000 | [diff] [blame] | 773 | Instructions.push_back(Inst); | 
|  | 774 | } | 
|  | 775 |  | 
| Rafael Espindola | b40a71f | 2010-12-29 01:42:56 +0000 | [diff] [blame] | 776 | EmitCFIInstructions(streamer, Instructions, NULL); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 777 |  | 
|  | 778 | // Padding | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 779 | streamer.EmitValueToAlignment(IsEH ? 4 : asmInfo.getPointerSize()); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 780 |  | 
|  | 781 | streamer.EmitLabel(sectionEnd); | 
|  | 782 | return *sectionStart; | 
|  | 783 | } | 
|  | 784 |  | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 785 | MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, | 
|  | 786 | const MCSymbol &cieStart, | 
| Rafael Espindola | 9f270da | 2011-05-10 03:01:39 +0000 | [diff] [blame] | 787 | const MCDwarfFrameInfo &frame) { | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 788 | MCContext &context = streamer.getContext(); | 
|  | 789 | MCSymbol *fdeStart = context.CreateTempSymbol(); | 
|  | 790 | MCSymbol *fdeEnd = context.CreateTempSymbol(); | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 791 | const TargetAsmInfo &TAsmInfo = context.getTargetAsmInfo(); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 792 |  | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 793 | if (!TAsmInfo.isFunctionEHFrameSymbolPrivate() && IsEH) { | 
| Daniel Dunbar | b47426b | 2011-05-03 21:33:37 +0000 | [diff] [blame] | 794 | MCSymbol *EHSym = context.GetOrCreateSymbol( | 
|  | 795 | frame.Function->getName() + Twine(".eh")); | 
| Rafael Espindola | 8bca410 | 2011-04-28 12:50:37 +0000 | [diff] [blame] | 796 | streamer.EmitEHSymAttributes(frame.Function, EHSym); | 
| Rafael Espindola | a8cfb87 | 2011-04-28 02:46:42 +0000 | [diff] [blame] | 797 | streamer.EmitLabel(EHSym); | 
|  | 798 | } | 
|  | 799 |  | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 800 | // Length | 
|  | 801 | const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); | 
| Rafael Espindola | 9266cc4 | 2011-04-27 01:43:49 +0000 | [diff] [blame] | 802 | streamer.EmitAbsValue(Length, 4); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 803 |  | 
|  | 804 | streamer.EmitLabel(fdeStart); | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 805 |  | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 806 | // CIE Pointer | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 807 | const MCAsmInfo &asmInfo = context.getAsmInfo(); | 
| Rafael Espindola | 0d450dc | 2011-05-10 15:20:23 +0000 | [diff] [blame] | 808 | if (IsEH) { | 
|  | 809 | const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, | 
|  | 810 | 0); | 
|  | 811 | streamer.EmitAbsValue(offset, 4); | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 812 | } else if (!asmInfo.doesDwarfRequireRelocationForSectionOffset()) { | 
|  | 813 | const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, | 
|  | 814 | cieStart, 0); | 
|  | 815 | streamer.EmitAbsValue(offset, 4); | 
| Rafael Espindola | 0d450dc | 2011-05-10 15:20:23 +0000 | [diff] [blame] | 816 | } else { | 
|  | 817 | streamer.EmitSymbolValue(&cieStart, 4); | 
|  | 818 | } | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 819 | unsigned fdeEncoding = TAsmInfo.getFDEEncoding(UsingCFI); | 
| Rafael Espindola | abf9af6 | 2011-04-22 00:08:43 +0000 | [diff] [blame] | 820 | unsigned size = getSizeForEncoding(streamer, fdeEncoding); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 821 |  | 
|  | 822 | // PC Begin | 
| Rafael Espindola | 9989ef4 | 2011-05-10 22:28:35 +0000 | [diff] [blame] | 823 | unsigned PCBeginEncoding = IsEH ? fdeEncoding : | 
|  | 824 | (unsigned)dwarf::DW_EH_PE_absptr; | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 825 | unsigned PCBeginSize = getSizeForEncoding(streamer, PCBeginEncoding); | 
|  | 826 | EmitSymbol(streamer, *frame.Begin, PCBeginEncoding); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 827 |  | 
|  | 828 | // PC Range | 
|  | 829 | const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, | 
|  | 830 | *frame.End, 0); | 
| Rafael Espindola | 9266cc4 | 2011-04-27 01:43:49 +0000 | [diff] [blame] | 831 | streamer.EmitAbsValue(Range, size); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 832 |  | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 833 | if (IsEH) { | 
|  | 834 | // Augmentation Data Length | 
|  | 835 | unsigned augmentationLength = 0; | 
| Rafael Espindola | 1f6c875 | 2011-04-29 21:50:57 +0000 | [diff] [blame] | 836 |  | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 837 | if (frame.Lsda) | 
|  | 838 | augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); | 
| Rafael Espindola | 1f6c875 | 2011-04-29 21:50:57 +0000 | [diff] [blame] | 839 |  | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 840 | streamer.EmitULEB128IntValue(augmentationLength); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 841 |  | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 842 | // Augmentation Data | 
|  | 843 | if (frame.Lsda) | 
|  | 844 | EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding); | 
|  | 845 | } | 
| Rafael Espindola | 4892dff | 2011-04-29 03:06:29 +0000 | [diff] [blame] | 846 |  | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 847 | // Call Frame Instructions | 
|  | 848 |  | 
| Rafael Espindola | b40a71f | 2010-12-29 01:42:56 +0000 | [diff] [blame] | 849 | EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); | 
| Rafael Espindola | 5bba084 | 2010-12-28 04:15:37 +0000 | [diff] [blame] | 850 |  | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 851 | // Padding | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 852 | streamer.EmitValueToAlignment(PCBeginSize); | 
| Rafael Espindola | dfe125c | 2010-12-17 00:28:02 +0000 | [diff] [blame] | 853 |  | 
|  | 854 | return fdeEnd; | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 855 | } | 
|  | 856 |  | 
| Benjamin Kramer | 1928236 | 2010-12-30 22:34:44 +0000 | [diff] [blame] | 857 | namespace { | 
|  | 858 | struct CIEKey { | 
|  | 859 | static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1); } | 
|  | 860 | static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0); } | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 861 |  | 
| Benjamin Kramer | 1928236 | 2010-12-30 22:34:44 +0000 | [diff] [blame] | 862 | CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_, | 
|  | 863 | unsigned LsdaEncoding_) : Personality(Personality_), | 
|  | 864 | PersonalityEncoding(PersonalityEncoding_), | 
|  | 865 | LsdaEncoding(LsdaEncoding_) { | 
|  | 866 | } | 
|  | 867 | const MCSymbol* Personality; | 
|  | 868 | unsigned PersonalityEncoding; | 
|  | 869 | unsigned LsdaEncoding; | 
|  | 870 | }; | 
|  | 871 | } | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 872 |  | 
|  | 873 | namespace llvm { | 
|  | 874 | template <> | 
|  | 875 | struct DenseMapInfo<CIEKey> { | 
|  | 876 | static CIEKey getEmptyKey() { | 
| Benjamin Kramer | 1928236 | 2010-12-30 22:34:44 +0000 | [diff] [blame] | 877 | return CIEKey::getEmptyKey(); | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 878 | } | 
|  | 879 | static CIEKey getTombstoneKey() { | 
| Benjamin Kramer | 1928236 | 2010-12-30 22:34:44 +0000 | [diff] [blame] | 880 | return CIEKey::getTombstoneKey(); | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 881 | } | 
|  | 882 | static unsigned getHashValue(const CIEKey &Key) { | 
|  | 883 | FoldingSetNodeID ID; | 
|  | 884 | ID.AddPointer(Key.Personality); | 
|  | 885 | ID.AddInteger(Key.PersonalityEncoding); | 
|  | 886 | ID.AddInteger(Key.LsdaEncoding); | 
|  | 887 | return ID.ComputeHash(); | 
|  | 888 | } | 
|  | 889 | static bool isEqual(const CIEKey &LHS, | 
|  | 890 | const CIEKey &RHS) { | 
|  | 891 | return LHS.Personality == RHS.Personality && | 
|  | 892 | LHS.PersonalityEncoding == RHS.PersonalityEncoding && | 
|  | 893 | LHS.LsdaEncoding == RHS.LsdaEncoding; | 
|  | 894 | } | 
|  | 895 | }; | 
|  | 896 | } | 
|  | 897 |  | 
| Rafael Espindola | 5426a9e | 2011-05-01 04:49:54 +0000 | [diff] [blame] | 898 | void MCDwarfFrameEmitter::Emit(MCStreamer &streamer, | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 899 | bool usingCFI, | 
|  | 900 | bool isEH) { | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 901 | MCContext &context = streamer.getContext(); | 
| Rafael Espindola | dfe125c | 2010-12-17 00:28:02 +0000 | [diff] [blame] | 902 | const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 903 | const MCSection §ion = isEH ? | 
| Bill Wendling | e3cd13f | 2011-06-23 01:06:23 +0000 | [diff] [blame^] | 904 | *asmInfo.getEHFrameSection() : | 
|  | 905 | *asmInfo.getDwarfFrameSection(); | 
| Rafael Espindola | 774466a | 2011-05-10 03:26:21 +0000 | [diff] [blame] | 906 | streamer.SwitchSection(§ion); | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 907 | MCSymbol *SectionStart = context.CreateTempSymbol(); | 
|  | 908 | streamer.EmitLabel(SectionStart); | 
| Rafael Espindola | 9099813 | 2011-04-29 02:42:28 +0000 | [diff] [blame] | 909 |  | 
| Rafael Espindola | dfe125c | 2010-12-17 00:28:02 +0000 | [diff] [blame] | 910 | MCSymbol *fdeEnd = NULL; | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 911 | DenseMap<CIEKey, const MCSymbol*> CIEStarts; | 
| Rafael Espindola | e3a0e98 | 2011-05-10 20:59:42 +0000 | [diff] [blame] | 912 | FrameEmitterImpl Emitter(usingCFI, isEH, SectionStart); | 
| Rafael Espindola | d7c8cca | 2010-12-26 20:20:31 +0000 | [diff] [blame] | 913 |  | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 914 | const MCSymbol *DummyDebugKey = NULL; | 
| Rafael Espindola | dfe125c | 2010-12-17 00:28:02 +0000 | [diff] [blame] | 915 | for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { | 
| Rafael Espindola | d7c8cca | 2010-12-26 20:20:31 +0000 | [diff] [blame] | 916 | const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); | 
| Rafael Espindola | bdc3167 | 2010-12-27 15:56:22 +0000 | [diff] [blame] | 917 | CIEKey key(frame.Personality, frame.PersonalityEncoding, | 
|  | 918 | frame.LsdaEncoding); | 
| Rafael Espindola | 40a7dbb | 2011-05-10 03:54:12 +0000 | [diff] [blame] | 919 | const MCSymbol *&cieStart = isEH ? CIEStarts[key] : DummyDebugKey; | 
| Bill Wendling | e3cd13f | 2011-06-23 01:06:23 +0000 | [diff] [blame^] | 920 | if (isEH && asmInfo.getSupportsCompactUnwindInfo() && | 
|  | 921 | Emitter.EmitCompactUnwind(streamer, frame)) | 
|  | 922 | continue; | 
|  | 923 |  | 
| Rafael Espindola | d7c8cca | 2010-12-26 20:20:31 +0000 | [diff] [blame] | 924 | if (!cieStart) | 
| Rafael Espindola | 25f492e | 2011-04-12 16:12:03 +0000 | [diff] [blame] | 925 | cieStart = &Emitter.EmitCIE(streamer, frame.Personality, | 
|  | 926 | frame.PersonalityEncoding, frame.Lsda, | 
|  | 927 | frame.LsdaEncoding); | 
| Bill Wendling | e3cd13f | 2011-06-23 01:06:23 +0000 | [diff] [blame^] | 928 |  | 
| Rafael Espindola | 9f270da | 2011-05-10 03:01:39 +0000 | [diff] [blame] | 929 | fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame); | 
| Bill Wendling | e3cd13f | 2011-06-23 01:06:23 +0000 | [diff] [blame^] | 930 |  | 
| Rafael Espindola | dfe125c | 2010-12-17 00:28:02 +0000 | [diff] [blame] | 931 | if (i != n - 1) | 
|  | 932 | streamer.EmitLabel(fdeEnd); | 
|  | 933 | } | 
| Rafael Espindola | d7c8cca | 2010-12-26 20:20:31 +0000 | [diff] [blame] | 934 |  | 
| Rafael Espindola | dfe125c | 2010-12-17 00:28:02 +0000 | [diff] [blame] | 935 | streamer.EmitValueToAlignment(asmInfo.getPointerSize()); | 
|  | 936 | if (fdeEnd) | 
|  | 937 | streamer.EmitLabel(fdeEnd); | 
| Rafael Espindola | 89b9372 | 2010-12-10 07:39:47 +0000 | [diff] [blame] | 938 | } | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 939 |  | 
|  | 940 | void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, | 
|  | 941 | uint64_t AddrDelta) { | 
|  | 942 | SmallString<256> Tmp; | 
|  | 943 | raw_svector_ostream OS(Tmp); | 
| Rafael Espindola | 4eafe10 | 2011-05-08 14:35:21 +0000 | [diff] [blame] | 944 | MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS); | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 945 | Streamer.EmitBytes(OS.str(), /*AddrSpace=*/0); | 
|  | 946 | } | 
|  | 947 |  | 
|  | 948 | void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, | 
| Rafael Espindola | 4eafe10 | 2011-05-08 14:35:21 +0000 | [diff] [blame] | 949 | raw_ostream &OS) { | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 950 | // FIXME: Assumes the code alignment factor is 1. | 
| Rafael Espindola | 3b78cdc | 2010-12-28 23:38:03 +0000 | [diff] [blame] | 951 | if (AddrDelta == 0) { | 
| Rafael Espindola | 4eafe10 | 2011-05-08 14:35:21 +0000 | [diff] [blame] | 952 | } else if (isUIntN(6, AddrDelta)) { | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 953 | uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; | 
|  | 954 | OS << Opcode; | 
| Rafael Espindola | 4eafe10 | 2011-05-08 14:35:21 +0000 | [diff] [blame] | 955 | } else if (isUInt<8>(AddrDelta)) { | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 956 | OS << uint8_t(dwarf::DW_CFA_advance_loc1); | 
|  | 957 | OS << uint8_t(AddrDelta); | 
| Rafael Espindola | 4eafe10 | 2011-05-08 14:35:21 +0000 | [diff] [blame] | 958 | } else if (isUInt<16>(AddrDelta)) { | 
| Rafael Espindola | a7e4505 | 2010-12-29 02:30:49 +0000 | [diff] [blame] | 959 | // FIXME: check what is the correct behavior on a big endian machine. | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 960 | OS << uint8_t(dwarf::DW_CFA_advance_loc2); | 
| Rafael Espindola | a7e4505 | 2010-12-29 02:30:49 +0000 | [diff] [blame] | 961 | OS << uint8_t( AddrDelta       & 0xff); | 
|  | 962 | OS << uint8_t((AddrDelta >> 8) & 0xff); | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 963 | } else { | 
| Rafael Espindola | a7e4505 | 2010-12-29 02:30:49 +0000 | [diff] [blame] | 964 | // FIXME: check what is the correct behavior on a big endian machine. | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 965 | assert(isUInt<32>(AddrDelta)); | 
|  | 966 | OS << uint8_t(dwarf::DW_CFA_advance_loc4); | 
| Rafael Espindola | a7e4505 | 2010-12-29 02:30:49 +0000 | [diff] [blame] | 967 | OS << uint8_t( AddrDelta        & 0xff); | 
|  | 968 | OS << uint8_t((AddrDelta >> 8)  & 0xff); | 
|  | 969 | OS << uint8_t((AddrDelta >> 16) & 0xff); | 
|  | 970 | OS << uint8_t((AddrDelta >> 24) & 0xff); | 
|  | 971 |  | 
| Rafael Espindola | 245a1e2 | 2010-12-28 05:39:27 +0000 | [diff] [blame] | 972 | } | 
|  | 973 | } |