rename the dwarf class to DwarfPrinter. This matches the filename
[oota-llvm.git] / lib / CodeGen / AsmPrinter / DwarfPrinter.cpp
1 //===--- 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"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/MC/MCSymbol.h"
22 #include "llvm/Target/TargetData.h"
23 #include "llvm/Target/TargetFrameInfo.h"
24 #include "llvm/Target/TargetRegisterInfo.h"
25 #include "llvm/Support/Dwarf.h"
26 #include "llvm/Support/ErrorHandling.h"
27 using namespace llvm;
28
29 DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
30                            const char *flavor)
31 : O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()),
32   RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL),
33   SubprogramCount(0), Flavor(flavor), SetCounter(1) {}
34
35 void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const {
36   if (isInSection && MAI->getDwarfSectionOffsetDirective())
37     O << MAI->getDwarfSectionOffsetDirective();
38   else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
39     O << MAI->getData32bitsDirective();
40   else
41     O << MAI->getData64bitsDirective();
42 }
43
44 /// PrintLabelName - Print label name in form used by Dwarf writer.
45 ///
46 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
47   O << MAI->getPrivateGlobalPrefix() << Tag;
48   if (Number) O << Number;
49 }
50 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
51                                   const char *Suffix) const {
52   O << MAI->getPrivateGlobalPrefix() << Tag;
53   if (Number) O << Number;
54   O << Suffix;
55 }
56
57 /// EmitLabel - Emit location label for internal use by Dwarf.
58 ///
59 void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
60   PrintLabelName(Tag, Number);
61   O << ":\n";
62 }
63
64 /// EmitReference - Emit a reference to a label.
65 ///
66 void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
67                                  bool IsPCRelative, bool Force32Bit) const {
68   PrintRelDirective(Force32Bit);
69   PrintLabelName(Tag, Number);
70   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
71 }
72 void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative,
73                                  bool Force32Bit) const {
74   PrintRelDirective(Force32Bit);
75   O << Name;
76   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
77 }
78
79 void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative,
80                                  bool Force32Bit) const {
81   PrintRelDirective(Force32Bit);
82   O << *Sym;
83   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
84 }
85
86 /// EmitDifference - Emit the difference between two labels.  Some assemblers do
87 /// not behave with absolute expressions with data directives, so there is an
88 /// option (needsSet) to use an intermediary set expression.
89 void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi,
90                                   const char *TagLo, unsigned NumberLo,
91                                   bool IsSmall) {
92   if (MAI->needsSet()) {
93     O << "\t.set\t";
94     PrintLabelName("set", SetCounter, Flavor);
95     O << ",";
96     PrintLabelName(TagHi, NumberHi);
97     O << "-";
98     PrintLabelName(TagLo, NumberLo);
99     O << "\n";
100
101     PrintRelDirective(IsSmall);
102     PrintLabelName("set", SetCounter, Flavor);
103     ++SetCounter;
104   } else {
105     PrintRelDirective(IsSmall);
106     PrintLabelName(TagHi, NumberHi);
107     O << "-";
108     PrintLabelName(TagLo, NumberLo);
109   }
110 }
111
112 void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
113                                      unsigned LabelNumber,
114                                      unsigned SectionNumber,
115                                      bool IsSmall, bool isEH,
116                                      bool useSet) {
117   bool printAbsolute = false;
118   if (isEH)
119     printAbsolute = MAI->isAbsoluteEHSectionOffsets();
120   else
121     printAbsolute = MAI->isAbsoluteDebugSectionOffsets();
122
123   if (MAI->needsSet() && useSet) {
124     O << "\t.set\t";
125     PrintLabelName("set", SetCounter, Flavor);
126     O << ",";
127     PrintLabelName(Label, LabelNumber);
128
129     if (!printAbsolute) {
130       O << "-";
131       PrintLabelName(Section, SectionNumber);
132     }
133
134     O << "\n";
135     PrintRelDirective(IsSmall);
136     PrintLabelName("set", SetCounter, Flavor);
137     ++SetCounter;
138   } else {
139     PrintRelDirective(IsSmall, true);
140     PrintLabelName(Label, LabelNumber);
141
142     if (!printAbsolute) {
143       O << "-";
144       PrintLabelName(Section, SectionNumber);
145     }
146   }
147 }
148
149 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
150 /// frame.
151 void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
152                                   const std::vector<MachineMove> &Moves,
153                                   bool isEH) {
154   int stackGrowth =
155     Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
156     TargetFrameInfo::StackGrowsUp ?
157     TD->getPointerSize() : -TD->getPointerSize();
158   bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
159
160   for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
161     const MachineMove &Move = Moves[i];
162     unsigned LabelID = Move.getLabelID();
163
164     if (LabelID) {
165       LabelID = MMI->MappedLabel(LabelID);
166
167       // Throw out move if the label is invalid.
168       if (!LabelID) continue;
169     }
170
171     const MachineLocation &Dst = Move.getDestination();
172     const MachineLocation &Src = Move.getSource();
173
174     // Advance row if new location.
175     if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
176       Asm->EmitInt8(dwarf::DW_CFA_advance_loc4);
177       Asm->EOL("DW_CFA_advance_loc4");
178       EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
179       Asm->O << '\n';
180
181       BaseLabelID = LabelID;
182       BaseLabel = "label";
183       IsLocal = true;
184     }
185
186     // If advancing cfa.
187     if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
188       if (!Src.isReg()) {
189         if (Src.getReg() == MachineLocation::VirtualFP) {
190           Asm->EmitInt8(dwarf::DW_CFA_def_cfa_offset);
191           Asm->EOL("DW_CFA_def_cfa_offset");
192         } else {
193           Asm->EmitInt8(dwarf::DW_CFA_def_cfa);
194           Asm->EOL("DW_CFA_def_cfa");
195           Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), isEH));
196           Asm->EOL("Register");
197         }
198
199         int Offset = -Src.getOffset();
200
201         Asm->EmitULEB128Bytes(Offset);
202         Asm->EOL("Offset");
203       } else {
204         llvm_unreachable("Machine move not supported yet.");
205       }
206     } else if (Src.isReg() &&
207                Src.getReg() == MachineLocation::VirtualFP) {
208       if (Dst.isReg()) {
209         Asm->EmitInt8(dwarf::DW_CFA_def_cfa_register);
210         Asm->EOL("DW_CFA_def_cfa_register");
211         Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH));
212         Asm->EOL("Register");
213       } else {
214         llvm_unreachable("Machine move not supported yet.");
215       }
216     } else {
217       unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
218       int Offset = Dst.getOffset() / stackGrowth;
219
220       if (Offset < 0) {
221         Asm->EmitInt8(dwarf::DW_CFA_offset_extended_sf);
222         Asm->EOL("DW_CFA_offset_extended_sf");
223         Asm->EmitULEB128Bytes(Reg);
224         Asm->EOL("Reg");
225         Asm->EmitSLEB128Bytes(Offset);
226         Asm->EOL("Offset");
227       } else if (Reg < 64) {
228         Asm->EmitInt8(dwarf::DW_CFA_offset + Reg);
229         Asm->EOL("DW_CFA_offset + Reg (" + Twine(Reg) + ")");
230         Asm->EmitULEB128Bytes(Offset);
231         Asm->EOL("Offset");
232       } else {
233         Asm->EmitInt8(dwarf::DW_CFA_offset_extended);
234         Asm->EOL("DW_CFA_offset_extended");
235         Asm->EmitULEB128Bytes(Reg);
236         Asm->EOL("Reg");
237         Asm->EmitULEB128Bytes(Offset);
238         Asm->EOL("Offset");
239       }
240     }
241   }
242 }