eliminate the TargetLowering::UsesGlobalOffsetTable bool, which is
[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/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"
28 using namespace llvm;
29
30 DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
31                            const char *flavor)
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) {}
35
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();
41   else
42     O << MAI->getData64bitsDirective();
43 }
44
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;
51   }
52   Asm->O << '\n';
53 }
54
55 static const char *DecodeDWARFEncoding(unsigned Encoding) {
56   switch (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";
76   }
77   
78   return "<unknown encoding>";
79 }
80
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) {
87     if (Desc != 0)
88       Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " +
89                                   Twine(DecodeDWARFEncoding(Val)));
90     else
91       Asm->OutStreamer.AddComment(Twine("Encoding = ") +
92                                   DecodeDWARFEncoding(Val));
93   }
94
95   Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
96 }
97
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) + ")");
104     else
105       Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val));
106   }
107   Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
108 }
109
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);
114     
115   if (MAI->hasLEB128()) {
116     O << "\t.sleb128\t" << Value;
117     Asm->OutStreamer.AddBlankLine();
118     return;
119   }
120
121   // If we don't have .sleb128, emit as .bytes.
122   int Sign = Value >> (8 * sizeof(Value) - 1);
123   bool IsMore;
124   
125   do {
126     unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
127     Value >>= 7;
128     IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
129     if (IsMore) Byte |= 0x80;
130     
131     Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
132   } while (IsMore);
133 }
134
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);
139  
140   if (MAI->hasLEB128()) {
141     O << "\t.uleb128\t" << Value;
142     Asm->OutStreamer.AddBlankLine();
143     return;
144   }
145   
146   // If we don't have .uleb128, emit as .bytes.
147   do {
148     unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
149     Value >>= 7;
150     if (Value) Byte |= 0x80;
151     Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
152   } while (Value);
153 }
154
155
156 /// PrintLabelName - Print label name in form used by Dwarf writer.
157 ///
158 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
159   O << MAI->getPrivateGlobalPrefix() << Tag;
160   if (Number) O << Number;
161 }
162 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
163                                   const char *Suffix) const {
164   O << MAI->getPrivateGlobalPrefix() << Tag;
165   if (Number) O << Number;
166   O << Suffix;
167 }
168
169 /// EmitLabel - Emit location label for internal use by Dwarf.
170 ///
171 void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
172   PrintLabelName(Tag, Number);
173   O << ":\n";
174 }
175
176 /// EmitReference - Emit a reference to a label.
177 ///
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();
183 }
184 void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative,
185                                  bool Force32Bit) const {
186   PrintRelDirective(Force32Bit);
187   O << Name;
188   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
189 }
190
191 void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative,
192                                  bool Force32Bit) const {
193   PrintRelDirective(Force32Bit);
194   O << *Sym;
195   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
196 }
197
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,
203                                   bool IsSmall) {
204   if (MAI->needsSet()) {
205     O << "\t.set\t";
206     PrintLabelName("set", SetCounter, Flavor);
207     O << ",";
208     PrintLabelName(TagHi, NumberHi);
209     O << "-";
210     PrintLabelName(TagLo, NumberLo);
211     O << "\n";
212
213     PrintRelDirective(IsSmall);
214     PrintLabelName("set", SetCounter, Flavor);
215     ++SetCounter;
216   } else {
217     PrintRelDirective(IsSmall);
218     PrintLabelName(TagHi, NumberHi);
219     O << "-";
220     PrintLabelName(TagLo, NumberLo);
221   }
222 }
223
224 void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
225                                      unsigned LabelNumber,
226                                      unsigned SectionNumber,
227                                      bool IsSmall, bool isEH,
228                                      bool useSet) {
229   bool printAbsolute = false;
230   if (isEH)
231     printAbsolute = MAI->isAbsoluteEHSectionOffsets();
232   else
233     printAbsolute = MAI->isAbsoluteDebugSectionOffsets();
234
235   if (MAI->needsSet() && useSet) {
236     O << "\t.set\t";
237     PrintLabelName("set", SetCounter, Flavor);
238     O << ",";
239     PrintLabelName(Label, LabelNumber);
240
241     if (!printAbsolute) {
242       O << "-";
243       PrintLabelName(Section, SectionNumber);
244     }
245
246     O << "\n";
247     PrintRelDirective(IsSmall);
248     PrintLabelName("set", SetCounter, Flavor);
249     ++SetCounter;
250     O << "\n";
251   } else {
252     PrintRelDirective(IsSmall, true);
253     PrintLabelName(Label, LabelNumber);
254
255     if (!printAbsolute) {
256       O << "-";
257       PrintLabelName(Section, SectionNumber);
258     }
259     O << "\n";
260   }
261 }
262
263 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
264 /// frame.
265 void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
266                                   const std::vector<MachineMove> &Moves,
267                                   bool isEH) {
268   int stackGrowth =
269     Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
270     TargetFrameInfo::StackGrowsUp ?
271     TD->getPointerSize() : -TD->getPointerSize();
272   bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
273
274   for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
275     const MachineMove &Move = Moves[i];
276     unsigned LabelID = Move.getLabelID();
277
278     if (LabelID) {
279       LabelID = MMI->MappedLabel(LabelID);
280
281       // Throw out move if the label is invalid.
282       if (!LabelID) continue;
283     }
284
285     const MachineLocation &Dst = Move.getDestination();
286     const MachineLocation &Src = Move.getSource();
287
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);
292       Asm->O << '\n';
293
294       BaseLabelID = LabelID;
295       BaseLabel = "label";
296       IsLocal = true;
297     }
298
299     // If advancing cfa.
300     if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
301       if (!Src.isReg()) {
302         if (Src.getReg() == MachineLocation::VirtualFP) {
303           EmitCFAByte(dwarf::DW_CFA_def_cfa_offset);
304         } else {
305           EmitCFAByte(dwarf::DW_CFA_def_cfa);
306           EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register");
307         }
308
309         int Offset = -Src.getOffset();
310         EmitULEB128(Offset, "Offset");
311       } else {
312         llvm_unreachable("Machine move not supported yet.");
313       }
314     } else if (Src.isReg() &&
315                Src.getReg() == MachineLocation::VirtualFP) {
316       if (Dst.isReg()) {
317         EmitCFAByte(dwarf::DW_CFA_def_cfa_register);
318         EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register");
319       } else {
320         llvm_unreachable("Machine move not supported yet.");
321       }
322     } else {
323       unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
324       int Offset = Dst.getOffset() / stackGrowth;
325
326       if (Offset < 0) {
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");
333       } else {
334         EmitCFAByte(dwarf::DW_CFA_offset_extended);
335         EmitULEB128(Reg, "Reg");
336         EmitULEB128(Offset, "Offset");
337       }
338     }
339   }
340 }