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/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"
29 Dwarf::Dwarf(raw_ostream
&OS
, AsmPrinter
*A
, const MCAsmInfo
*T
,
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) {}
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();
41 O
<< MAI
->getData64bitsDirective();
44 /// PrintLabelName - Print label name in form used by Dwarf writer.
46 void Dwarf::PrintLabelName(const char *Tag
, unsigned Number
) const {
47 O
<< MAI
->getPrivateGlobalPrefix() << Tag
;
48 if (Number
) O
<< Number
;
50 void Dwarf::PrintLabelName(const char *Tag
, unsigned Number
,
51 const char *Suffix
) const {
52 O
<< MAI
->getPrivateGlobalPrefix() << Tag
;
53 if (Number
) O
<< Number
;
57 /// EmitLabel - Emit location label for internal use by Dwarf.
59 void Dwarf::EmitLabel(const char *Tag
, unsigned Number
) const {
60 PrintLabelName(Tag
, Number
);
64 /// EmitReference - Emit a reference to a label.
66 void Dwarf::EmitReference(const char *Tag
, unsigned Number
,
67 bool IsPCRelative
, bool Force32Bit
) const {
68 PrintRelDirective(Force32Bit
);
69 PrintLabelName(Tag
, Number
);
70 if (IsPCRelative
) O
<< "-" << MAI
->getPCSymbol();
72 void Dwarf::EmitReference(const std::string
&Name
, bool IsPCRelative
,
73 bool Force32Bit
) const {
74 PrintRelDirective(Force32Bit
);
76 if (IsPCRelative
) O
<< "-" << MAI
->getPCSymbol();
79 /// EmitDifference - Emit the difference between two labels. Some assemblers do
80 /// not behave with absolute expressions with data directives, so there is an
81 /// option (needsSet) to use an intermediary set expression.
82 void Dwarf::EmitDifference(const char *TagHi
, unsigned NumberHi
,
83 const char *TagLo
, unsigned NumberLo
,
85 if (MAI
->needsSet()) {
87 PrintLabelName("set", SetCounter
, Flavor
);
89 PrintLabelName(TagHi
, NumberHi
);
91 PrintLabelName(TagLo
, NumberLo
);
94 PrintRelDirective(IsSmall
);
95 PrintLabelName("set", SetCounter
, Flavor
);
98 PrintRelDirective(IsSmall
);
99 PrintLabelName(TagHi
, NumberHi
);
101 PrintLabelName(TagLo
, NumberLo
);
105 void Dwarf::EmitSectionOffset(const char* Label
, const char* Section
,
106 unsigned LabelNumber
, unsigned SectionNumber
,
107 bool IsSmall
, bool isEH
,
109 bool printAbsolute
= false;
111 printAbsolute
= MAI
->isAbsoluteEHSectionOffsets();
113 printAbsolute
= MAI
->isAbsoluteDebugSectionOffsets();
115 if (MAI
->needsSet() && useSet
) {
117 PrintLabelName("set", SetCounter
, Flavor
);
119 PrintLabelName(Label
, LabelNumber
);
121 if (!printAbsolute
) {
123 PrintLabelName(Section
, SectionNumber
);
127 PrintRelDirective(IsSmall
);
128 PrintLabelName("set", SetCounter
, Flavor
);
131 PrintRelDirective(IsSmall
, true);
132 PrintLabelName(Label
, LabelNumber
);
134 if (!printAbsolute
) {
136 PrintLabelName(Section
, SectionNumber
);
141 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
143 void Dwarf::EmitFrameMoves(const char *BaseLabel
, unsigned BaseLabelID
,
144 const std::vector
<MachineMove
> &Moves
, bool isEH
) {
146 Asm
->TM
.getFrameInfo()->getStackGrowthDirection() ==
147 TargetFrameInfo::StackGrowsUp
?
148 TD
->getPointerSize() : -TD
->getPointerSize();
149 bool IsLocal
= BaseLabel
&& strcmp(BaseLabel
, "label") == 0;
151 for (unsigned i
= 0, N
= Moves
.size(); i
< N
; ++i
) {
152 const MachineMove
&Move
= Moves
[i
];
153 unsigned LabelID
= Move
.getLabelID();
156 LabelID
= MMI
->MappedLabel(LabelID
);
158 // Throw out move if the label is invalid.
159 if (!LabelID
) continue;
162 const MachineLocation
&Dst
= Move
.getDestination();
163 const MachineLocation
&Src
= Move
.getSource();
165 // Advance row if new location.
166 if (BaseLabel
&& LabelID
&& (BaseLabelID
!= LabelID
|| !IsLocal
)) {
167 Asm
->EmitInt8(dwarf::DW_CFA_advance_loc4
);
168 Asm
->EOL("DW_CFA_advance_loc4");
169 EmitDifference("label", LabelID
, BaseLabel
, BaseLabelID
, true);
172 BaseLabelID
= LabelID
;
178 if (Dst
.isReg() && Dst
.getReg() == MachineLocation::VirtualFP
) {
180 if (Src
.getReg() == MachineLocation::VirtualFP
) {
181 Asm
->EmitInt8(dwarf::DW_CFA_def_cfa_offset
);
182 Asm
->EOL("DW_CFA_def_cfa_offset");
184 Asm
->EmitInt8(dwarf::DW_CFA_def_cfa
);
185 Asm
->EOL("DW_CFA_def_cfa");
186 Asm
->EmitULEB128Bytes(RI
->getDwarfRegNum(Src
.getReg(), isEH
));
187 Asm
->EOL("Register");
190 int Offset
= -Src
.getOffset();
192 Asm
->EmitULEB128Bytes(Offset
);
195 llvm_unreachable("Machine move not supported yet.");
197 } else if (Src
.isReg() &&
198 Src
.getReg() == MachineLocation::VirtualFP
) {
200 Asm
->EmitInt8(dwarf::DW_CFA_def_cfa_register
);
201 Asm
->EOL("DW_CFA_def_cfa_register");
202 Asm
->EmitULEB128Bytes(RI
->getDwarfRegNum(Dst
.getReg(), isEH
));
203 Asm
->EOL("Register");
205 llvm_unreachable("Machine move not supported yet.");
208 unsigned Reg
= RI
->getDwarfRegNum(Src
.getReg(), isEH
);
209 int Offset
= Dst
.getOffset() / stackGrowth
;
212 Asm
->EmitInt8(dwarf::DW_CFA_offset_extended_sf
);
213 Asm
->EOL("DW_CFA_offset_extended_sf");
214 Asm
->EmitULEB128Bytes(Reg
);
216 Asm
->EmitSLEB128Bytes(Offset
);
218 } else if (Reg
< 64) {
219 Asm
->EmitInt8(dwarf::DW_CFA_offset
+ Reg
);
220 if (Asm
->isVerbose())
221 Asm
->EOL("DW_CFA_offset + Reg (" + utostr(Reg
) + ")");
224 Asm
->EmitULEB128Bytes(Offset
);
227 Asm
->EmitInt8(dwarf::DW_CFA_offset_extended
);
228 Asm
->EOL("DW_CFA_offset_extended");
229 Asm
->EmitULEB128Bytes(Reg
);
231 Asm
->EmitULEB128Bytes(Offset
);