1 //===--- lib/CodeGen/DwarfPrinter.cpp - Dwarf Printer ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Emit general DWARF directives.
12 //===----------------------------------------------------------------------===//
14 #include "DwarfPrinter.h"
15 #include "llvm/Module.h"
16 #include "llvm/CodeGen/AsmPrinter.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/MC/MCStreamer.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/Target/TargetData.h"
24 #include "llvm/Target/TargetFrameInfo.h"
25 #include "llvm/Target/TargetRegisterInfo.h"
26 #include "llvm/Support/Dwarf.h"
27 #include "llvm/Support/ErrorHandling.h"
30 DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
32 : O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()),
33 RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL),
34 SubprogramCount(0), Flavor(flavor), SetCounter(1) {}
36 void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const {
37 if (isInSection && MAI->getDwarfSectionOffsetDirective())
38 O << MAI->getDwarfSectionOffsetDirective();
39 else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
40 O << MAI->getData32bitsDirective();
42 O << MAI->getData64bitsDirective();
45 /// EOL - Print a newline character to asm stream. If a comment is present
46 /// then it will be printed first. Comments should not contain '\n'.
47 void DwarfPrinter::EOL(const Twine &Comment) const {
48 if (Asm->VerboseAsm && !Comment.isTriviallyEmpty()) {
49 Asm->O.PadToColumn(MAI->getCommentColumn());
50 Asm->O << Asm->MAI->getCommentString() << ' ' << Comment;
55 static const char *DecodeDWARFEncoding(unsigned Encoding) {
57 case dwarf::DW_EH_PE_absptr: return "absptr";
58 case dwarf::DW_EH_PE_omit: return "omit";
59 case dwarf::DW_EH_PE_pcrel: return "pcrel";
60 case dwarf::DW_EH_PE_udata4: return "udata4";
61 case dwarf::DW_EH_PE_udata8: return "udata8";
62 case dwarf::DW_EH_PE_sdata4: return "sdata4";
63 case dwarf::DW_EH_PE_sdata8: return "sdata8";
64 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4";
65 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4";
66 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8";
67 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8";
68 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4:
69 return "indirect pcrel udata4";
70 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4:
71 return "indirect pcrel sdata4";
72 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8:
73 return "indirect pcrel udata8";
74 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8:
75 return "indirect pcrel sdata8";
78 return "<unknown encoding>";
81 /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
82 /// encoding. If verbose assembly output is enabled, we output comments
83 /// describing the encoding. Desc is an optional string saying what the
84 /// encoding is specifying (e.g. "LSDA").
85 void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) {
86 if (Asm->VerboseAsm) {
88 Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " +
89 Twine(DecodeDWARFEncoding(Val)));
91 Asm->OutStreamer.AddComment(Twine("Encoding = ") +
92 DecodeDWARFEncoding(Val));
95 Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
98 /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
99 void DwarfPrinter::EmitCFAByte(unsigned Val) {
100 if (Asm->VerboseAsm) {
101 if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64)
102 Asm->OutStreamer.AddComment("DW_CFA_offset + Reg (" +
103 Twine(Val-dwarf::DW_CFA_offset) + ")");
105 Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val));
107 Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
110 /// EmitSLEB128 - emit the specified signed leb128 value.
111 void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const {
112 if (Asm->VerboseAsm && Desc)
113 Asm->OutStreamer.AddComment(Desc);
115 if (MAI->hasLEB128()) {
116 O << "\t.sleb128\t" << Value;
117 Asm->OutStreamer.AddBlankLine();
121 // If we don't have .sleb128, emit as .bytes.
122 int Sign = Value >> (8 * sizeof(Value) - 1);
126 unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
128 IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
129 if (IsMore) Byte |= 0x80;
131 Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
135 /// EmitULEB128 - emit the specified signed leb128 value.
136 void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc) const {
137 if (Asm->VerboseAsm && Desc)
138 Asm->OutStreamer.AddComment(Desc);
140 if (MAI->hasLEB128()) {
141 O << "\t.uleb128\t" << Value;
142 Asm->OutStreamer.AddBlankLine();
146 // If we don't have .uleb128, emit as .bytes.
148 unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
150 if (Value) Byte |= 0x80;
151 Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
156 /// PrintLabelName - Print label name in form used by Dwarf writer.
158 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
159 O << MAI->getPrivateGlobalPrefix() << Tag;
160 if (Number) O << Number;
162 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
163 const char *Suffix) const {
164 O << MAI->getPrivateGlobalPrefix() << Tag;
165 if (Number) O << Number;
169 /// EmitLabel - Emit location label for internal use by Dwarf.
171 void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
172 PrintLabelName(Tag, Number);
176 /// EmitReference - Emit a reference to a label.
178 void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
179 bool IsPCRelative, bool Force32Bit) const {
180 PrintRelDirective(Force32Bit);
181 PrintLabelName(Tag, Number);
182 if (IsPCRelative) O << "-" << MAI->getPCSymbol();
184 void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative,
185 bool Force32Bit) const {
186 PrintRelDirective(Force32Bit);
188 if (IsPCRelative) O << "-" << MAI->getPCSymbol();
191 void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative,
192 bool Force32Bit) const {
193 PrintRelDirective(Force32Bit);
195 if (IsPCRelative) O << "-" << MAI->getPCSymbol();
198 /// EmitDifference - Emit the difference between two labels. Some assemblers do
199 /// not behave with absolute expressions with data directives, so there is an
200 /// option (needsSet) to use an intermediary set expression.
201 void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi,
202 const char *TagLo, unsigned NumberLo,
204 if (MAI->needsSet()) {
206 PrintLabelName("set", SetCounter, Flavor);
208 PrintLabelName(TagHi, NumberHi);
210 PrintLabelName(TagLo, NumberLo);
213 PrintRelDirective(IsSmall);
214 PrintLabelName("set", SetCounter, Flavor);
217 PrintRelDirective(IsSmall);
218 PrintLabelName(TagHi, NumberHi);
220 PrintLabelName(TagLo, NumberLo);
224 void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
225 unsigned LabelNumber,
226 unsigned SectionNumber,
227 bool IsSmall, bool isEH,
229 bool printAbsolute = false;
231 printAbsolute = MAI->isAbsoluteEHSectionOffsets();
233 printAbsolute = MAI->isAbsoluteDebugSectionOffsets();
235 if (MAI->needsSet() && useSet) {
237 PrintLabelName("set", SetCounter, Flavor);
239 PrintLabelName(Label, LabelNumber);
241 if (!printAbsolute) {
243 PrintLabelName(Section, SectionNumber);
247 PrintRelDirective(IsSmall);
248 PrintLabelName("set", SetCounter, Flavor);
252 PrintRelDirective(IsSmall, true);
253 PrintLabelName(Label, LabelNumber);
255 if (!printAbsolute) {
257 PrintLabelName(Section, SectionNumber);
263 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
265 void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
266 const std::vector<MachineMove> &Moves,
269 Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
270 TargetFrameInfo::StackGrowsUp ?
271 TD->getPointerSize() : -TD->getPointerSize();
272 bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
274 for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
275 const MachineMove &Move = Moves[i];
276 unsigned LabelID = Move.getLabelID();
279 LabelID = MMI->MappedLabel(LabelID);
281 // Throw out move if the label is invalid.
282 if (!LabelID) continue;
285 const MachineLocation &Dst = Move.getDestination();
286 const MachineLocation &Src = Move.getSource();
288 // Advance row if new location.
289 if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
290 EmitCFAByte(dwarf::DW_CFA_advance_loc4);
291 EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
294 BaseLabelID = LabelID;
300 if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
302 if (Src.getReg() == MachineLocation::VirtualFP) {
303 EmitCFAByte(dwarf::DW_CFA_def_cfa_offset);
305 EmitCFAByte(dwarf::DW_CFA_def_cfa);
306 EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register");
309 int Offset = -Src.getOffset();
310 EmitULEB128(Offset, "Offset");
312 llvm_unreachable("Machine move not supported yet.");
314 } else if (Src.isReg() &&
315 Src.getReg() == MachineLocation::VirtualFP) {
317 EmitCFAByte(dwarf::DW_CFA_def_cfa_register);
318 EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register");
320 llvm_unreachable("Machine move not supported yet.");
323 unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
324 int Offset = Dst.getOffset() / stackGrowth;
327 EmitCFAByte(dwarf::DW_CFA_offset_extended_sf);
328 EmitULEB128(Reg, "Reg");
329 EmitSLEB128(Offset, "Offset");
330 } else if (Reg < 64) {
331 EmitCFAByte(dwarf::DW_CFA_offset + Reg);
332 EmitULEB128(Offset, "Offset");
334 EmitCFAByte(dwarf::DW_CFA_offset_extended);
335 EmitULEB128(Reg, "Reg");
336 EmitULEB128(Offset, "Offset");