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