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