MC'ize padding when padding the ULEB128 value.
[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     Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
163   } while (IsMore);
164 }
165
166 /// EmitULEB128 - emit the specified signed leb128 value.
167 void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc,
168                                unsigned PadTo) const {
169   if (Asm->VerboseAsm && Desc)
170     Asm->OutStreamer.AddComment(Desc);
171  
172   if (MAI->hasLEB128() && PadTo == 0) {
173     O << "\t.uleb128\t" << Value;
174     Asm->OutStreamer.AddBlankLine();
175     return;
176   }
177   
178   // If we don't have .uleb128 or we want to emit padding, emit as .bytes.
179   do {
180     unsigned char Byte = static_cast<unsigned char>(Value & 0x7f);
181     Value >>= 7;
182     if (Value || PadTo != 0) Byte |= 0x80;
183     Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0);
184   } while (Value);
185
186   if (PadTo) {
187     if (PadTo > 1)
188       Asm->OutStreamer.EmitFill(PadTo - 1, 0x80/*fillval*/, 0/*addrspace*/);
189     Asm->OutStreamer.EmitFill(1, 0/*fillval*/, 0/*addrspace*/);
190   }
191 }
192
193
194 /// PrintLabelName - Print label name in form used by Dwarf writer.
195 ///
196 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number) const {
197   O << MAI->getPrivateGlobalPrefix() << Tag;
198   if (Number) O << Number;
199 }
200 void DwarfPrinter::PrintLabelName(const char *Tag, unsigned Number,
201                                   const char *Suffix) const {
202   O << MAI->getPrivateGlobalPrefix() << Tag;
203   if (Number) O << Number;
204   O << Suffix;
205 }
206
207 /// EmitLabel - Emit location label for internal use by Dwarf.
208 ///
209 void DwarfPrinter::EmitLabel(const char *Tag, unsigned Number) const {
210   PrintLabelName(Tag, Number);
211   O << ":\n";
212 }
213
214 /// EmitReference - Emit a reference to a label.
215 ///
216 void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
217                                  bool IsPCRelative, bool Force32Bit) const {
218   PrintRelDirective(Force32Bit);
219   PrintLabelName(Tag, Number);
220   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
221 }
222 void DwarfPrinter::EmitReference(const std::string &Name, bool IsPCRelative,
223                                  bool Force32Bit) const {
224   PrintRelDirective(Force32Bit);
225   O << Name;
226   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
227 }
228
229 void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative,
230                                  bool Force32Bit) const {
231   PrintRelDirective(Force32Bit);
232   O << *Sym;
233   if (IsPCRelative) O << "-" << MAI->getPCSymbol();
234 }
235
236 void DwarfPrinter::EmitReference(const char *Tag, unsigned Number,
237                                  unsigned Encoding) const {
238   SmallString<64> Name;
239   raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
240                             << Tag << Number;
241
242   MCSymbol *Sym = Asm->OutContext.GetOrCreateSymbol(Name.str());
243   EmitReference(Sym, Encoding);
244 }
245
246 void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const {
247   const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
248
249   PrintRelDirective(Encoding);
250   O << *TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);;
251 }
252
253 void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const {
254   const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
255
256   PrintRelDirective(Encoding);
257   O << *TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang,
258                                               Asm->MMI, Encoding);;
259 }
260
261 /// EmitDifference - Emit the difference between two labels.  If this assembler
262 /// supports .set, we emit a .set of a temporary and then use it in the .word.
263 void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi,
264                                   const char *TagLo, unsigned NumberLo,
265                                   bool IsSmall) {
266   if (MAI->hasSetDirective()) {
267     // FIXME: switch to OutStreamer.EmitAssignment.
268     O << "\t.set\t";
269     PrintLabelName("set", SetCounter, Flavor);
270     O << ",";
271     PrintLabelName(TagHi, NumberHi);
272     O << "-";
273     PrintLabelName(TagLo, NumberLo);
274     O << "\n";
275
276     PrintRelDirective(IsSmall);
277     PrintLabelName("set", SetCounter, Flavor);
278     ++SetCounter;
279   } else {
280     PrintRelDirective(IsSmall);
281     PrintLabelName(TagHi, NumberHi);
282     O << "-";
283     PrintLabelName(TagLo, NumberLo);
284   }
285 }
286
287 void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section,
288                                      unsigned LabelNumber,
289                                      unsigned SectionNumber,
290                                      bool IsSmall, bool isEH,
291                                      bool useSet) {
292   bool printAbsolute = false;
293   if (isEH)
294     printAbsolute = MAI->isAbsoluteEHSectionOffsets();
295   else
296     printAbsolute = MAI->isAbsoluteDebugSectionOffsets();
297
298   if (MAI->hasSetDirective() && useSet) {
299     // FIXME: switch to OutStreamer.EmitAssignment.
300     O << "\t.set\t";
301     PrintLabelName("set", SetCounter, Flavor);
302     O << ",";
303     PrintLabelName(Label, LabelNumber);
304
305     if (!printAbsolute) {
306       O << "-";
307       PrintLabelName(Section, SectionNumber);
308     }
309
310     O << "\n";
311     PrintRelDirective(IsSmall);
312     PrintLabelName("set", SetCounter, Flavor);
313     ++SetCounter;
314   } else {
315     PrintRelDirective(IsSmall, true);
316     PrintLabelName(Label, LabelNumber);
317
318     if (!printAbsolute) {
319       O << "-";
320       PrintLabelName(Section, SectionNumber);
321     }
322   }
323 }
324
325 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
326 /// frame.
327 void DwarfPrinter::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
328                                   const std::vector<MachineMove> &Moves,
329                                   bool isEH) {
330   int stackGrowth =
331     Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
332     TargetFrameInfo::StackGrowsUp ?
333     TD->getPointerSize() : -TD->getPointerSize();
334   bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
335
336   for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
337     const MachineMove &Move = Moves[i];
338     unsigned LabelID = Move.getLabelID();
339
340     if (LabelID) {
341       LabelID = MMI->MappedLabel(LabelID);
342
343       // Throw out move if the label is invalid.
344       if (!LabelID) continue;
345     }
346
347     const MachineLocation &Dst = Move.getDestination();
348     const MachineLocation &Src = Move.getSource();
349
350     // Advance row if new location.
351     if (BaseLabel && LabelID && (BaseLabelID != LabelID || !IsLocal)) {
352       EmitCFAByte(dwarf::DW_CFA_advance_loc4);
353       EmitDifference("label", LabelID, BaseLabel, BaseLabelID, true);
354       Asm->O << '\n';
355
356       BaseLabelID = LabelID;
357       BaseLabel = "label";
358       IsLocal = true;
359     }
360
361     // If advancing cfa.
362     if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
363       if (!Src.isReg()) {
364         if (Src.getReg() == MachineLocation::VirtualFP) {
365           EmitCFAByte(dwarf::DW_CFA_def_cfa_offset);
366         } else {
367           EmitCFAByte(dwarf::DW_CFA_def_cfa);
368           EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register");
369         }
370
371         int Offset = -Src.getOffset();
372         EmitULEB128(Offset, "Offset");
373       } else {
374         llvm_unreachable("Machine move not supported yet.");
375       }
376     } else if (Src.isReg() &&
377                Src.getReg() == MachineLocation::VirtualFP) {
378       if (Dst.isReg()) {
379         EmitCFAByte(dwarf::DW_CFA_def_cfa_register);
380         EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register");
381       } else {
382         llvm_unreachable("Machine move not supported yet.");
383       }
384     } else {
385       unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
386       int Offset = Dst.getOffset() / stackGrowth;
387
388       if (Offset < 0) {
389         EmitCFAByte(dwarf::DW_CFA_offset_extended_sf);
390         EmitULEB128(Reg, "Reg");
391         EmitSLEB128(Offset, "Offset");
392       } else if (Reg < 64) {
393         EmitCFAByte(dwarf::DW_CFA_offset + Reg);
394         EmitULEB128(Offset, "Offset");
395       } else {
396         EmitCFAByte(dwarf::DW_CFA_offset_extended);
397         EmitULEB128(Reg, "Reg");
398         EmitULEB128(Offset, "Offset");
399       }
400     }
401   }
402 }