blob: 99b46d61a0b180ea924a892009e90db3050c59f3 [file] [log] [blame]
Bill Wendling88423ee2009-05-15 00:11:17 +00001//===--- lib/CodeGen/DwarfPrinter.cpp - Dwarf Printer ---------------------===//
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// Emit general DWARF directives.
11//
12//===----------------------------------------------------------------------===//
13
14#include "DwarfPrinter.h"
15#include "llvm/Module.h"
16#include "llvm/CodeGen/AsmPrinter.h"
17#include "llvm/CodeGen/MachineFrameInfo.h"
David Greeneeea1f4c2009-08-19 21:59:18 +000018#include "llvm/CodeGen/MachineFunction.h"
Bill Wendling88423ee2009-05-15 00:11:17 +000019#include "llvm/CodeGen/MachineModuleInfo.h"
Chris Lattneraf76e592009-08-22 20:48:53 +000020#include "llvm/MC/MCAsmInfo.h"
Chris Lattnerf61ed8e2010-01-22 22:38:16 +000021#include "llvm/MC/MCStreamer.h"
Chris Lattner858431d2010-01-16 18:50:28 +000022#include "llvm/MC/MCSymbol.h"
Bill Wendling88423ee2009-05-15 00:11:17 +000023#include "llvm/Target/TargetData.h"
24#include "llvm/Target/TargetFrameInfo.h"
25#include "llvm/Target/TargetRegisterInfo.h"
Chris Lattner23132b12009-08-24 03:52:50 +000026#include "llvm/Support/Dwarf.h"
27#include "llvm/Support/ErrorHandling.h"
Bill Wendling88423ee2009-05-15 00:11:17 +000028using namespace llvm;
29
Chris Lattner066c9ac2010-01-22 22:23:57 +000030DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
31 const char *flavor)
Chris Lattner33adcfb2009-08-22 21:43:10 +000032: O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()),
Bill Wendling88423ee2009-05-15 00:11:17 +000033 RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL),
34 SubprogramCount(0), Flavor(flavor), SetCounter(1) {}
35
Chris Lattner066c9ac2010-01-22 22:23:57 +000036void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const {
Chris Lattner33adcfb2009-08-22 21:43:10 +000037 if (isInSection && MAI->getDwarfSectionOffsetDirective())
38 O << MAI->getDwarfSectionOffsetDirective();
Bill Wendling88423ee2009-05-15 00:11:17 +000039 else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
Chris Lattner33adcfb2009-08-22 21:43:10 +000040 O << MAI->getData32bitsDirective();
Bill Wendling88423ee2009-05-15 00:11:17 +000041 else
Chris Lattner33adcfb2009-08-22 21:43:10 +000042 O << MAI->getData64bitsDirective();
Bill Wendling88423ee2009-05-15 00:11:17 +000043}
44
Chris Lattnerf61ed8e2010-01-22 22:38:16 +000045static const char *DecodeDWARFEncoding(unsigned Encoding) {
46 switch (Encoding) {
47 case dwarf::DW_EH_PE_absptr: return "absptr";
48 case dwarf::DW_EH_PE_omit: return "omit";
49 case dwarf::DW_EH_PE_pcrel: return "pcrel";
50 case dwarf::DW_EH_PE_udata4: return "udata4";
51 case dwarf::DW_EH_PE_udata8: return "udata8";
52 case dwarf::DW_EH_PE_sdata4: return "sdata4";
53 case dwarf::DW_EH_PE_sdata8: return "sdata8";
54 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4";
55 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4";
56 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8";
57 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8";
58 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4:
59 return "indirect pcrel udata4";
60 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4:
61 return "indirect pcrel sdata4";
62 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8:
63 return "indirect pcrel udata8";
64 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8:
65 return "indirect pcrel sdata8";
66 }
67
68 return "<unknown encoding>";
69}
70
71/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
72/// encoding. If verbose assembly output is enabled, we output comments
73/// describing the encoding. Desc is an optional string saying what the
74/// encoding is specifying (e.g. "LSDA").
75void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) {
76 if (Asm->VerboseAsm) {
77 if (Desc != 0)
78 Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " +
79 Twine(DecodeDWARFEncoding(Val)));
80 else
81 Asm->OutStreamer.AddComment(Twine("Encoding = ") +
82 DecodeDWARFEncoding(Val));
83 }
84
85 Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
86}
87
88
Bill Wendling88423ee2009-05-15 00:11:17 +000089/// PrintLabelName - Print label name in form used by Dwarf writer.
90///
Chris Lattner066c9ac2010-01-22 22:23:57 +000091void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
Jim Grosbacha01d3462009-09-01 16:43:35 +000092 O << MAI->getPrivateGlobalPrefix() << Tag;
Bill Wendling88423ee2009-05-15 00:11:17 +000093 if (Number) O << Number;
94}
Chris Lattner066c9ac2010-01-22 22:23:57 +000095void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
96 const char *Suffix) const {
Jim Grosbacha01d3462009-09-01 16:43:35 +000097 O << MAI->getPrivateGlobalPrefix() << Tag;
Bill Wendling88423ee2009-05-15 00:11:17 +000098 if (Number) O << Number;
99 O << Suffix;
100}
101
102/// EmitLabel - Emit location label for internal use by Dwarf.
103///
Chris Lattner066c9ac2010-01-22 22:23:57 +0000104void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
Jim Grosbacha01d3462009-09-01 16:43:35 +0000105 PrintLabelName(Tag, Number);
Bill Wendling88423ee2009-05-15 00:11:17 +0000106 O << ":\n";
107}
108
109/// EmitReference - Emit a reference to a label.
110///
Chris Lattner066c9ac2010-01-22 22:23:57 +0000111void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
112 bool IsPCRelative, bool Force32Bit) const {
Bill Wendling88423ee2009-05-15 00:11:17 +0000113 PrintRelDirective(Force32Bit);
114 PrintLabelName(Tag, Number);
Chris Lattner33adcfb2009-08-22 21:43:10 +0000115 if (IsPCRelative) O << "-" << MAI->getPCSymbol();
Bill Wendling88423ee2009-05-15 00:11:17 +0000116}
Chris Lattner066c9ac2010-01-22 22:23:57 +0000117void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative,
118 bool Force32Bit) const {
Bill Wendling88423ee2009-05-15 00:11:17 +0000119 PrintRelDirective(Force32Bit);
120 O << Name;
Chris Lattner33adcfb2009-08-22 21:43:10 +0000121 if (IsPCRelative) O << "-" << MAI->getPCSymbol();
Bill Wendling88423ee2009-05-15 00:11:17 +0000122}
123
Chris Lattner066c9ac2010-01-22 22:23:57 +0000124void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative,
125 bool Force32Bit) const {
Chris Lattner858431d2010-01-16 18:50:28 +0000126 PrintRelDirective(Force32Bit);
Chris Lattner10b318b2010-01-17 21:43:43 +0000127 O << *Sym;
Chris Lattner858431d2010-01-16 18:50:28 +0000128 if (IsPCRelative) O << "-" << MAI->getPCSymbol();
129}
130
Bill Wendling88423ee2009-05-15 00:11:17 +0000131/// EmitDifference - Emit the difference between two labels. Some assemblers do
132/// not behave with absolute expressions with data directives, so there is an
133/// option (needsSet) to use an intermediary set expression.
Chris Lattner066c9ac2010-01-22 22:23:57 +0000134void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi,
135 const char *TagLo, unsigned NumberLo,
136 bool IsSmall) {
Chris Lattner33adcfb2009-08-22 21:43:10 +0000137 if (MAI->needsSet()) {
Bill Wendling88423ee2009-05-15 00:11:17 +0000138 O << "\t.set\t";
139 PrintLabelName("set", SetCounter, Flavor);
140 O << ",";
141 PrintLabelName(TagHi, NumberHi);
142 O << "-";
143 PrintLabelName(TagLo, NumberLo);
144 O << "\n";
145
146 PrintRelDirective(IsSmall);
147 PrintLabelName("set", SetCounter, Flavor);
148 ++SetCounter;
149 } else {
150 PrintRelDirective(IsSmall);
151 PrintLabelName(TagHi, NumberHi);
152 O << "-";
153 PrintLabelName(TagLo, NumberLo);
154 }
155}
156
Chris Lattner066c9ac2010-01-22 22:23:57 +0000157void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
158 unsigned LabelNumber,
159 unsigned SectionNumber,
160 bool IsSmall, bool isEH,
161 bool useSet) {
Bill Wendling88423ee2009-05-15 00:11:17 +0000162 bool printAbsolute = false;
163 if (isEH)
Chris Lattner33adcfb2009-08-22 21:43:10 +0000164 printAbsolute = MAI->isAbsoluteEHSectionOffsets();
Bill Wendling88423ee2009-05-15 00:11:17 +0000165 else
Chris Lattner33adcfb2009-08-22 21:43:10 +0000166 printAbsolute = MAI->isAbsoluteDebugSectionOffsets();
Bill Wendling88423ee2009-05-15 00:11:17 +0000167
Chris Lattner33adcfb2009-08-22 21:43:10 +0000168 if (MAI->needsSet() && useSet) {
Bill Wendling88423ee2009-05-15 00:11:17 +0000169 O << "\t.set\t";
170 PrintLabelName("set", SetCounter, Flavor);
171 O << ",";
172 PrintLabelName(Label, LabelNumber);
173
174 if (!printAbsolute) {
175 O << "-";
176 PrintLabelName(Section, SectionNumber);
177 }
178
179 O << "\n";
180 PrintRelDirective(IsSmall);
181 PrintLabelName("set", SetCounter, Flavor);
182 ++SetCounter;
183 } else {
184 PrintRelDirective(IsSmall, true);
185 PrintLabelName(Label, LabelNumber);
186
187 if (!printAbsolute) {
188 O << "-";
189 PrintLabelName(Section, SectionNumber);
190 }
191 }
192}
193
194/// EmitFrameMoves - Emit frame instructions to describe the layout of the
195/// frame.
Chris Lattner066c9ac2010-01-22 22:23:57 +0000196void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
197 const std::vector<MachineMove> &Moves,
198 bool isEH) {
Bill Wendling88423ee2009-05-15 00:11:17 +0000199 int stackGrowth =
200 Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
201 TargetFrameInfo::StackGrowsUp ?
202 TD->getPointerSize() : -TD->getPointerSize();
203 bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
204
205 for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
206 const MachineMove &Move = Moves[i];
207 unsigned LabelID = Move.getLabelID();
208
209 if (LabelID) {
210 LabelID = MMI->MappedLabel(LabelID);
211
212 // Throw out move if the label is invalid.
213 if (!LabelID) continue;
214 }
215
216 const MachineLocation &Dst = Move.getDestination();
217 const MachineLocation &Src = Move.getSource();
218
219 // Advance row if new location.
220 if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
221 Asm->EmitInt8(dwarf::DW_CFA_advance_loc4);
222 Asm->EOL("DW_CFA_advance_loc4");
223 EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
Chris Lattner0ad9c912010-01-22 22:09:00 +0000224 Asm->O << '\n';
Bill Wendling88423ee2009-05-15 00:11:17 +0000225
226 BaseLabelID = LabelID;
227 BaseLabel = "label";
228 IsLocal = true;
229 }
230
231 // If advancing cfa.
232 if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
233 if (!Src.isReg()) {
234 if (Src.getReg() == MachineLocation::VirtualFP) {
235 Asm->EmitInt8(dwarf::DW_CFA_def_cfa_offset);
236 Asm->EOL("DW_CFA_def_cfa_offset");
237 } else {
238 Asm->EmitInt8(dwarf::DW_CFA_def_cfa);
239 Asm->EOL("DW_CFA_def_cfa");
240 Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), isEH));
241 Asm->EOL("Register");
242 }
243
244 int Offset = -Src.getOffset();
245
246 Asm->EmitULEB128Bytes(Offset);
247 Asm->EOL("Offset");
248 } else {
Torok Edwinc23197a2009-07-14 16:55:14 +0000249 llvm_unreachable("Machine move not supported yet.");
Bill Wendling88423ee2009-05-15 00:11:17 +0000250 }
251 } else if (Src.isReg() &&
252 Src.getReg() == MachineLocation::VirtualFP) {
253 if (Dst.isReg()) {
254 Asm->EmitInt8(dwarf::DW_CFA_def_cfa_register);
255 Asm->EOL("DW_CFA_def_cfa_register");
256 Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH));
257 Asm->EOL("Register");
258 } else {
Torok Edwinc23197a2009-07-14 16:55:14 +0000259 llvm_unreachable("Machine move not supported yet.");
Bill Wendling88423ee2009-05-15 00:11:17 +0000260 }
261 } else {
262 unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
263 int Offset = Dst.getOffset() / stackGrowth;
264
265 if (Offset < 0) {
266 Asm->EmitInt8(dwarf::DW_CFA_offset_extended_sf);
267 Asm->EOL("DW_CFA_offset_extended_sf");
268 Asm->EmitULEB128Bytes(Reg);
269 Asm->EOL("Reg");
270 Asm->EmitSLEB128Bytes(Offset);
271 Asm->EOL("Offset");
272 } else if (Reg < 64) {
273 Asm->EmitInt8(dwarf::DW_CFA_offset + Reg);
Benjamin Kramer1efd4fd52010-01-17 07:46:39 +0000274 Asm->EOL("DW_CFA_offset + Reg (" + Twine(Reg) + ")");
Bill Wendling88423ee2009-05-15 00:11:17 +0000275 Asm->EmitULEB128Bytes(Offset);
276 Asm->EOL("Offset");
277 } else {
278 Asm->EmitInt8(dwarf::DW_CFA_offset_extended);
279 Asm->EOL("DW_CFA_offset_extended");
280 Asm->EmitULEB128Bytes(Reg);
281 Asm->EOL("Reg");
282 Asm->EmitULEB128Bytes(Offset);
283 Asm->EOL("Offset");
284 }
285 }
286 }
287}