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