1 //===--- lib/CodeGen/DwarfPrinter.cpp - Dwarf Printer ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Emit general DWARF directives.
12 //===----------------------------------------------------------------------===//
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/MachineModuleInfo.h"
19 #include "llvm/Support/Dwarf.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Target/TargetAsmInfo.h"
22 #include "llvm/Target/TargetData.h"
23 #include "llvm/Target/TargetFrameInfo.h"
24 #include "llvm/Target/TargetRegisterInfo.h"
28 Dwarf::Dwarf(raw_ostream
&OS
, AsmPrinter
*A
, const TargetAsmInfo
*T
,
30 : O(OS
), Asm(A
), TAI(T
), TD(Asm
->TM
.getTargetData()),
31 RI(Asm
->TM
.getRegisterInfo()), M(NULL
), MF(NULL
), MMI(NULL
),
32 SubprogramCount(0), Flavor(flavor
), SetCounter(1) {}
34 void Dwarf::PrintRelDirective(bool Force32Bit
, bool isInSection
) const {
35 if (isInSection
&& TAI
->getDwarfSectionOffsetDirective())
36 O
<< TAI
->getDwarfSectionOffsetDirective();
37 else if (Force32Bit
|| TD
->getPointerSize() == sizeof(int32_t))
38 O
<< TAI
->getData32bitsDirective();
40 O
<< TAI
->getData64bitsDirective();
43 /// PrintLabelName - Print label name in form used by Dwarf writer.
45 void Dwarf::PrintLabelName(const char *Tag
, unsigned Number
) const {
46 O
<< TAI
->getPrivateGlobalPrefix() << Tag
;
47 if (Number
) O
<< Number
;
49 void Dwarf::PrintLabelName(const char *Tag
, unsigned Number
,
50 const char *Suffix
) const {
51 O
<< TAI
->getPrivateGlobalPrefix() << Tag
;
52 if (Number
) O
<< Number
;
56 /// EmitLabel - Emit location label for internal use by Dwarf.
58 void Dwarf::EmitLabel(const char *Tag
, unsigned Number
) const {
59 PrintLabelName(Tag
, Number
);
63 /// EmitReference - Emit a reference to a label.
65 void Dwarf::EmitReference(const char *Tag
, unsigned Number
,
66 bool IsPCRelative
, bool Force32Bit
) const {
67 PrintRelDirective(Force32Bit
);
68 PrintLabelName(Tag
, Number
);
69 if (IsPCRelative
) O
<< "-" << TAI
->getPCSymbol();
71 void Dwarf::EmitReference(const std::string
&Name
, bool IsPCRelative
,
72 bool Force32Bit
) const {
73 PrintRelDirective(Force32Bit
);
75 if (IsPCRelative
) O
<< "-" << TAI
->getPCSymbol();
78 /// EmitDifference - Emit the difference between two labels. Some assemblers do
79 /// not behave with absolute expressions with data directives, so there is an
80 /// option (needsSet) to use an intermediary set expression.
81 void Dwarf::EmitDifference(const char *TagHi
, unsigned NumberHi
,
82 const char *TagLo
, unsigned NumberLo
,
84 if (TAI
->needsSet()) {
86 PrintLabelName("set", SetCounter
, Flavor
);
88 PrintLabelName(TagHi
, NumberHi
);
90 PrintLabelName(TagLo
, NumberLo
);
93 PrintRelDirective(IsSmall
);
94 PrintLabelName("set", SetCounter
, Flavor
);
97 PrintRelDirective(IsSmall
);
98 PrintLabelName(TagHi
, NumberHi
);
100 PrintLabelName(TagLo
, NumberLo
);
104 void Dwarf::EmitSectionOffset(const char* Label
, const char* Section
,
105 unsigned LabelNumber
, unsigned SectionNumber
,
106 bool IsSmall
, bool isEH
,
108 bool printAbsolute
= false;
110 printAbsolute
= TAI
->isAbsoluteEHSectionOffsets();
112 printAbsolute
= TAI
->isAbsoluteDebugSectionOffsets();
114 if (TAI
->needsSet() && useSet
) {
116 PrintLabelName("set", SetCounter
, Flavor
);
118 PrintLabelName(Label
, LabelNumber
);
120 if (!printAbsolute
) {
122 PrintLabelName(Section
, SectionNumber
);
126 PrintRelDirective(IsSmall
);
127 PrintLabelName("set", SetCounter
, Flavor
);
130 PrintRelDirective(IsSmall
, true);
131 PrintLabelName(Label
, LabelNumber
);
133 if (!printAbsolute
) {
135 PrintLabelName(Section
, SectionNumber
);
140 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
142 void Dwarf::EmitFrameMoves(const char *BaseLabel
, unsigned BaseLabelID
,
143 const std::vector
<MachineMove
> &Moves
, bool isEH
) {
145 Asm
->TM
.getFrameInfo()->getStackGrowthDirection() ==
146 TargetFrameInfo::StackGrowsUp
?
147 TD
->getPointerSize() : -TD
->getPointerSize();
148 bool IsLocal
= BaseLabel
&& strcmp(BaseLabel
, "label") == 0;
150 for (unsigned i
= 0, N
= Moves
.size(); i
< N
; ++i
) {
151 const MachineMove
&Move
= Moves
[i
];
152 unsigned LabelID
= Move
.getLabelID();
155 LabelID
= MMI
->MappedLabel(LabelID
);
157 // Throw out move if the label is invalid.
158 if (!LabelID
) continue;
161 const MachineLocation
&Dst
= Move
.getDestination();
162 const MachineLocation
&Src
= Move
.getSource();
164 // Advance row if new location.
165 if (BaseLabel
&& LabelID
&& (BaseLabelID
!= LabelID
|| !IsLocal
)) {
166 Asm
->EmitInt8(dwarf::DW_CFA_advance_loc4
);
167 Asm
->EOL("DW_CFA_advance_loc4");
168 EmitDifference("label", LabelID
, BaseLabel
, BaseLabelID
, true);
171 BaseLabelID
= LabelID
;
177 if (Dst
.isReg() && Dst
.getReg() == MachineLocation::VirtualFP
) {
179 if (Src
.getReg() == MachineLocation::VirtualFP
) {
180 Asm
->EmitInt8(dwarf::DW_CFA_def_cfa_offset
);
181 Asm
->EOL("DW_CFA_def_cfa_offset");
183 Asm
->EmitInt8(dwarf::DW_CFA_def_cfa
);
184 Asm
->EOL("DW_CFA_def_cfa");
185 Asm
->EmitULEB128Bytes(RI
->getDwarfRegNum(Src
.getReg(), isEH
));
186 Asm
->EOL("Register");
189 int Offset
= -Src
.getOffset();
191 Asm
->EmitULEB128Bytes(Offset
);
194 llvm_unreachable("Machine move not supported yet.");
196 } else if (Src
.isReg() &&
197 Src
.getReg() == MachineLocation::VirtualFP
) {
199 Asm
->EmitInt8(dwarf::DW_CFA_def_cfa_register
);
200 Asm
->EOL("DW_CFA_def_cfa_register");
201 Asm
->EmitULEB128Bytes(RI
->getDwarfRegNum(Dst
.getReg(), isEH
));
202 Asm
->EOL("Register");
204 llvm_unreachable("Machine move not supported yet.");
207 unsigned Reg
= RI
->getDwarfRegNum(Src
.getReg(), isEH
);
208 int Offset
= Dst
.getOffset() / stackGrowth
;
211 Asm
->EmitInt8(dwarf::DW_CFA_offset_extended_sf
);
212 Asm
->EOL("DW_CFA_offset_extended_sf");
213 Asm
->EmitULEB128Bytes(Reg
);
215 Asm
->EmitSLEB128Bytes(Offset
);
217 } else if (Reg
< 64) {
218 Asm
->EmitInt8(dwarf::DW_CFA_offset
+ Reg
);
219 if (Asm
->isVerbose())
220 Asm
->EOL("DW_CFA_offset + Reg (" + utostr(Reg
) + ")");
223 Asm
->EmitULEB128Bytes(Offset
);
226 Asm
->EmitInt8(dwarf::DW_CFA_offset_extended
);
227 Asm
->EOL("DW_CFA_offset_extended");
228 Asm
->EmitULEB128Bytes(Reg
);
230 Asm
->EmitULEB128Bytes(Offset
);