Before setting scope end marker, pay attention to scope begin marker and existing...
[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/MCContext.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSymbol.h"
25 #include "llvm/Target/TargetData.h"
26 #include "llvm/Target/TargetFrameInfo.h"
27 #include "llvm/Target/TargetLoweringObjectFile.h"
28 #include "llvm/Target/TargetRegisterInfo.h"
29 #include "llvm/Support/Dwarf.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/ADT/SmallString.h"
32 using namespace llvm;
33
34 DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T,
35                            const char *flavor)
36 : O(OS), Asm(A), MAI(T), TD(Asm->TM.getTargetData()),
37   RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL),
38   SubprogramCount(0), Flavor(flavor), SetCounter(1) {}
39
40 /// SizeOfEncodedValue - Return the size of the encoding in bytes.
41 unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const {
42   if (Encoding == dwarf::DW_EH_PE_omit)
43     return 0;
44
45   switch (Encoding & 0x07) {
46   case dwarf::DW_EH_PE_absptr:
47     return TD->getPointerSize();
48   case dwarf::DW_EH_PE_udata2:
49     return 2;
50   case dwarf::DW_EH_PE_udata4:
51     return 4;
52   case dwarf::DW_EH_PE_udata8:
53     return 8;
54   }
55
56   assert(0 && "Invalid encoded value.");
57   return 0;
58 }
59
60 void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const {
61   if (isInSection && MAI->getDwarfSectionOffsetDirective())
62     O << MAI->getDwarfSectionOffsetDirective();
63   else if (Force32Bit || TD->getPointerSize() == sizeof(int32_t))
64     O << MAI->getData32bitsDirective();
65   else
66     O << MAI->getData64bitsDirective();
67 }
68
69 void DwarfPrinter::PrintRelDirective(unsigned Encoding) const {
70   unsigned Size = SizeOfEncodedValue(Encoding);
71   assert((Size == 4 || Size == 8) && "Do not support other types or rels!");
72
73   O << (Size == 4 ?
74         MAI->getData32bitsDirective() : MAI->getData64bitsDirective());
75 }
76
77 /// EOL - Print a newline character to asm stream.  If a comment is present
78 /// then it will be printed first.  Comments should not contain '\n'.
79 void DwarfPrinter::EOL(const Twine &Comment) const {
80   if (Asm->VerboseAsm && !Comment.isTriviallyEmpty()) {
81     Asm->O.PadToColumn(MAI->getCommentColumn());
82     Asm->O << Asm->MAI->getCommentString() << ' ' << Comment;
83   }
84   Asm->O << '\n';
85 }
86
87 static const char *DecodeDWARFEncoding(unsigned Encoding) {
88   switch (Encoding) {
89   case dwarf::DW_EH_PE_absptr: return "absptr";
90   case dwarf::DW_EH_PE_omit:   return "omit";
91   case dwarf::DW_EH_PE_pcrel:  return "pcrel";
92   case dwarf::DW_EH_PE_udata4: return "udata4";
93   case dwarf::DW_EH_PE_udata8: return "udata8";
94   case dwarf::DW_EH_PE_sdata4: return "sdata4";
95   case dwarf::DW_EH_PE_sdata8: return "sdata8";
96   case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4";
97   case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4";
98   case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8";
99   case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8";
100   case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4:
101     return "indirect pcrel udata4";
102   case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4:
103     return "indirect pcrel sdata4";
104   case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8:
105     return "indirect pcrel udata8";
106   case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8:
107     return "indirect pcrel sdata8";
108   }
109   
110   return "<unknown encoding>";
111 }
112
113 /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
114 /// encoding.  If verbose assembly output is enabled, we output comments
115 /// describing the encoding.  Desc is an optional string saying what the
116 /// encoding is specifying (e.g. "LSDA").
117 void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) {
118   if (Asm->VerboseAsm) {
119     if (Desc != 0)
120       Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " +
121                                   Twine(DecodeDWARFEncoding(Val)));
122     else
123       Asm->OutStreamer.AddComment(Twine("Encoding = ") +
124                                   DecodeDWARFEncoding(Val));
125   }
126
127   Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
128 }
129
130 /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
131 void DwarfPrinter::EmitCFAByte(unsigned Val) {
132   if (Asm->VerboseAsm) {
133     if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64)
134       Asm->OutStreamer.AddComment("DW_CFA_offset + Reg (" + 
135                                   Twine(Val-dwarf::DW_CFA_offset) + ")");
136     else
137       Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val));
138   }
139   Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
140 }
141
142 /// EmitSLEB128 - emit the specified signed leb128 value.
143 void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const {
144   if (Asm->VerboseAsm && Desc)
145     Asm->OutStreamer.AddComment(Desc);
146     
147   if (MAI->hasLEB128()) {
148     O << "\t.sleb128\t" << Value;
149     Asm->OutStreamer.AddBlankLine();
150     return;
151   }
152
153   // If we don't have .sleb128, emit as .bytes.
154   int Sign = Value >> (8 * sizeof(Value) - 1);
155   bool IsMore;
156   
157   do {
158     unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
159     Value >>= 7;
160     IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
161     if (IsMore) Byte |= 0x80;
162     
163     Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
164   } while (IsMore);
165 }
166
167 /// EmitULEB128 - emit the specified signed leb128 value.
168 void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc) const {
169   if (Asm->VerboseAsm && Desc)
170     Asm->OutStreamer.AddComment(Desc);
171  
172   if (MAI->hasLEB128()) {
173     O << "\t.uleb128\t" << Value;
174     Asm->OutStreamer.AddBlankLine();
175     return;
176   }
177   
178   // If we don't have .uleb128, emit as .bytes.
179   do {
180     unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
181     Value >>= 7;
182     if (Value) Byte |= 0x80;
183     Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
184   } while (Value);
185 }
186
187
188 /// PrintLabelName - Print label name in form used by Dwarf writer.
189 ///
190 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
191   O << MAI->getPrivateGlobalPrefix() << Tag;
192   if (Number) O << Number;
193 }
194 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
195                                   const char *Suffix) const {
196   O << MAI->getPrivateGlobalPrefix() << Tag;
197   if (Number) O << Number;
198   O << Suffix;
199 }
200
201 /// EmitLabel - Emit location label for internal use by Dwarf.
202 ///
203 void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
204   PrintLabelName(Tag, Number);
205   O << ":\n";
206 }
207
208 /// EmitReference - Emit a reference to a label.
209 ///
210 void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
211                                  bool IsPCRelative, bool Force32Bit) const {
212   PrintRelDirective(Force32Bit);
213   PrintLabelName(Tag, Number);
214   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
215 }
216 void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative,
217                                  bool Force32Bit) const {
218   PrintRelDirective(Force32Bit);
219   O << Name;
220   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
221 }
222
223 void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative,
224                                  bool Force32Bit) const {
225   PrintRelDirective(Force32Bit);
226   O << *Sym;
227   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
228 }
229
230 void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
231                                  unsigned Encoding) const {
232   SmallString<64> Name;
233   raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
234                             << Tag << Number;
235
236   MCSymbol *Sym = Asm->OutContext.GetOrCreateSymbol(Name.str());
237   EmitReference(Sym, Encoding);
238 }
239
240 void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const {
241   const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
242
243   PrintRelDirective(Encoding);
244   O << *TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);;
245 }
246
247 void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const {
248   const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
249
250   PrintRelDirective(Encoding);
251   O << *TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang,
252                                               Asm->MMI, Encoding);;
253 }
254
255 /// EmitDifference - Emit the difference between two labels.  If this assembler
256 /// supports .set, we emit a .set of a temporary and then use it in the .word.
257 void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi,
258                                   const char *TagLo, unsigned NumberLo,
259                                   bool IsSmall) {
260   if (MAI->hasSetDirective()) {
261     // FIXME: switch to OutStreamer.EmitAssignment.
262     O << "\t.set\t";
263     PrintLabelName("set", SetCounter, Flavor);
264     O << ",";
265     PrintLabelName(TagHi, NumberHi);
266     O << "-";
267     PrintLabelName(TagLo, NumberLo);
268     O << "\n";
269
270     PrintRelDirective(IsSmall);
271     PrintLabelName("set", SetCounter, Flavor);
272     ++SetCounter;
273   } else {
274     PrintRelDirective(IsSmall);
275     PrintLabelName(TagHi, NumberHi);
276     O << "-";
277     PrintLabelName(TagLo, NumberLo);
278   }
279 }
280
281 void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
282                                      unsigned LabelNumber,
283                                      unsigned SectionNumber,
284                                      bool IsSmall, bool isEH,
285                                      bool useSet) {
286   bool printAbsolute = false;
287   if (isEH)
288     printAbsolute = MAI->isAbsoluteEHSectionOffsets();
289   else
290     printAbsolute = MAI->isAbsoluteDebugSectionOffsets();
291
292   if (MAI->hasSetDirective() && useSet) {
293     // FIXME: switch to OutStreamer.EmitAssignment.
294     O << "\t.set\t";
295     PrintLabelName("set", SetCounter, Flavor);
296     O << ",";
297     PrintLabelName(Label, LabelNumber);
298
299     if (!printAbsolute) {
300       O << "-";
301       PrintLabelName(Section, SectionNumber);
302     }
303
304     O << "\n";
305     PrintRelDirective(IsSmall);
306     PrintLabelName("set", SetCounter, Flavor);
307     ++SetCounter;
308   } else {
309     PrintRelDirective(IsSmall, true);
310     PrintLabelName(Label, LabelNumber);
311
312     if (!printAbsolute) {
313       O << "-";
314       PrintLabelName(Section, SectionNumber);
315     }
316   }
317 }
318
319 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
320 /// frame.
321 void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
322                                   const std::vector<MachineMove> &Moves,
323                                   bool isEH) {
324   int stackGrowth =
325     Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
326     TargetFrameInfo::StackGrowsUp ?
327     TD->getPointerSize() : -TD->getPointerSize();
328   bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
329
330   for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
331     const MachineMove &Move = Moves[i];
332     unsigned LabelID = Move.getLabelID();
333
334     if (LabelID) {
335       LabelID = MMI->MappedLabel(LabelID);
336
337       // Throw out move if the label is invalid.
338       if (!LabelID) continue;
339     }
340
341     const MachineLocation &Dst = Move.getDestination();
342     const MachineLocation &Src = Move.getSource();
343
344     // Advance row if new location.
345     if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
346       EmitCFAByte(dwarf::DW_CFA_advance_loc4);
347       EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
348       Asm->O << '\n';
349
350       BaseLabelID = LabelID;
351       BaseLabel = "label";
352       IsLocal = true;
353     }
354
355     // If advancing cfa.
356     if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
357       if (!Src.isReg()) {
358         if (Src.getReg() == MachineLocation::VirtualFP) {
359           EmitCFAByte(dwarf::DW_CFA_def_cfa_offset);
360         } else {
361           EmitCFAByte(dwarf::DW_CFA_def_cfa);
362           EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register");
363         }
364
365         int Offset = -Src.getOffset();
366         EmitULEB128(Offset, "Offset");
367       } else {
368         llvm_unreachable("Machine move not supported yet.");
369       }
370     } else if (Src.isReg() &&
371                Src.getReg() == MachineLocation::VirtualFP) {
372       if (Dst.isReg()) {
373         EmitCFAByte(dwarf::DW_CFA_def_cfa_register);
374         EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register");
375       } else {
376         llvm_unreachable("Machine move not supported yet.");
377       }
378     } else {
379       unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
380       int Offset = Dst.getOffset() / stackGrowth;
381
382       if (Offset < 0) {
383         EmitCFAByte(dwarf::DW_CFA_offset_extended_sf);
384         EmitULEB128(Reg, "Reg");
385         EmitSLEB128(Offset, "Offset");
386       } else if (Reg < 64) {
387         EmitCFAByte(dwarf::DW_CFA_offset + Reg);
388         EmitULEB128(Offset, "Offset");
389       } else {
390         EmitCFAByte(dwarf::DW_CFA_offset_extended);
391         EmitULEB128(Reg, "Reg");
392         EmitULEB128(Offset, "Offset");
393       }
394     }
395   }
396 }