1 //===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===//
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 // This file implements the Dwarf emissions parts of AsmPrinter.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "asm-printer"
15 #include "llvm/CodeGen/AsmPrinter.h"
16 #include "llvm/CodeGen/MachineLocation.h"
17 #include "llvm/MC/MCAsmInfo.h"
18 #include "llvm/MC/MCSection.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/MCSymbol.h"
21 #include "llvm/Target/TargetData.h"
22 #include "llvm/Target/TargetFrameLowering.h"
23 #include "llvm/Target/TargetLoweringObjectFile.h"
24 #include "llvm/Target/TargetMachine.h"
25 #include "llvm/Target/TargetRegisterInfo.h"
26 #include "llvm/ADT/Twine.h"
27 #include "llvm/Support/Dwarf.h"
30 //===----------------------------------------------------------------------===//
31 // Dwarf Emission Helper Routines
32 //===----------------------------------------------------------------------===//
34 /// EmitSLEB128 - emit the specified signed leb128 value.
35 void AsmPrinter::EmitSLEB128(int Value
, const char *Desc
) const {
36 if (isVerbose() && Desc
)
37 OutStreamer
.AddComment(Desc
);
39 if (MAI
->hasLEB128()) {
40 OutStreamer
.EmitSLEB128IntValue(Value
);
44 // If we don't have .sleb128, emit as .bytes.
45 int Sign
= Value
>> (8 * sizeof(Value
) - 1);
49 unsigned char Byte
= static_cast<unsigned char>(Value
& 0x7f);
51 IsMore
= Value
!= Sign
|| ((Byte
^ Sign
) & 0x40) != 0;
52 if (IsMore
) Byte
|= 0x80;
53 OutStreamer
.EmitIntValue(Byte
, 1, /*addrspace*/0);
57 /// EmitULEB128 - emit the specified signed leb128 value.
58 void AsmPrinter::EmitULEB128(unsigned Value
, const char *Desc
,
59 unsigned PadTo
) const {
60 if (isVerbose() && Desc
)
61 OutStreamer
.AddComment(Desc
);
63 // FIXME: Should we add a PadTo option to the streamer?
64 if (MAI
->hasLEB128() && PadTo
== 0) {
65 OutStreamer
.EmitULEB128IntValue(Value
);
69 // If we don't have .uleb128 or we want to emit padding, emit as .bytes.
71 unsigned char Byte
= static_cast<unsigned char>(Value
& 0x7f);
73 if (Value
|| PadTo
!= 0) Byte
|= 0x80;
74 OutStreamer
.EmitIntValue(Byte
, 1, /*addrspace*/0);
79 OutStreamer
.EmitFill(PadTo
- 1, 0x80/*fillval*/, 0/*addrspace*/);
80 OutStreamer
.EmitFill(1, 0/*fillval*/, 0/*addrspace*/);
84 /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
85 void AsmPrinter::EmitCFAByte(unsigned Val
) const {
87 if (Val
>= dwarf::DW_CFA_offset
&& Val
< dwarf::DW_CFA_offset
+64)
88 OutStreamer
.AddComment("DW_CFA_offset + Reg (" +
89 Twine(Val
-dwarf::DW_CFA_offset
) + ")");
91 OutStreamer
.AddComment(dwarf::CallFrameString(Val
));
93 OutStreamer
.EmitIntValue(Val
, 1, 0/*addrspace*/);
96 static const char *DecodeDWARFEncoding(unsigned Encoding
) {
98 case dwarf::DW_EH_PE_absptr
: return "absptr";
99 case dwarf::DW_EH_PE_omit
: return "omit";
100 case dwarf::DW_EH_PE_pcrel
: return "pcrel";
101 case dwarf::DW_EH_PE_udata4
: return "udata4";
102 case dwarf::DW_EH_PE_udata8
: return "udata8";
103 case dwarf::DW_EH_PE_sdata4
: return "sdata4";
104 case dwarf::DW_EH_PE_sdata8
: return "sdata8";
105 case dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_udata4
: return "pcrel udata4";
106 case dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_sdata4
: return "pcrel sdata4";
107 case dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_udata8
: return "pcrel udata8";
108 case dwarf::DW_EH_PE_pcrel
| dwarf::DW_EH_PE_sdata8
: return "pcrel sdata8";
109 case dwarf::DW_EH_PE_indirect
| dwarf::DW_EH_PE_pcrel
|dwarf::DW_EH_PE_udata4
:
110 return "indirect pcrel udata4";
111 case dwarf::DW_EH_PE_indirect
| dwarf::DW_EH_PE_pcrel
|dwarf::DW_EH_PE_sdata4
:
112 return "indirect pcrel sdata4";
113 case dwarf::DW_EH_PE_indirect
| dwarf::DW_EH_PE_pcrel
|dwarf::DW_EH_PE_udata8
:
114 return "indirect pcrel udata8";
115 case dwarf::DW_EH_PE_indirect
| dwarf::DW_EH_PE_pcrel
|dwarf::DW_EH_PE_sdata8
:
116 return "indirect pcrel sdata8";
119 return "<unknown encoding>";
123 /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
124 /// encoding. If verbose assembly output is enabled, we output comments
125 /// describing the encoding. Desc is an optional string saying what the
126 /// encoding is specifying (e.g. "LSDA").
127 void AsmPrinter::EmitEncodingByte(unsigned Val
, const char *Desc
) const {
130 OutStreamer
.AddComment(Twine(Desc
)+" Encoding = " +
131 Twine(DecodeDWARFEncoding(Val
)));
133 OutStreamer
.AddComment(Twine("Encoding = ") +
134 DecodeDWARFEncoding(Val
));
137 OutStreamer
.EmitIntValue(Val
, 1, 0/*addrspace*/);
140 /// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
141 unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding
) const {
142 if (Encoding
== dwarf::DW_EH_PE_omit
)
145 switch (Encoding
& 0x07) {
146 default: assert(0 && "Invalid encoded value.");
147 case dwarf::DW_EH_PE_absptr
: return TM
.getTargetData()->getPointerSize();
148 case dwarf::DW_EH_PE_udata2
: return 2;
149 case dwarf::DW_EH_PE_udata4
: return 4;
150 case dwarf::DW_EH_PE_udata8
: return 8;
154 void AsmPrinter::EmitReference(const MCSymbol
*Sym
, unsigned Encoding
) const {
155 const TargetLoweringObjectFile
&TLOF
= getObjFileLowering();
158 TLOF
.getExprForDwarfReference(Sym
, Mang
, MMI
, Encoding
, OutStreamer
);
159 OutStreamer
.EmitAbsValue(Exp
, GetSizeOfEncodedValue(Encoding
));
162 void AsmPrinter::EmitReference(const GlobalValue
*GV
, unsigned Encoding
)const{
163 const TargetLoweringObjectFile
&TLOF
= getObjFileLowering();
166 TLOF
.getExprForDwarfGlobalReference(GV
, Mang
, MMI
, Encoding
, OutStreamer
);
167 OutStreamer
.EmitValue(Exp
, GetSizeOfEncodedValue(Encoding
), /*addrspace*/0);
170 /// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its
171 /// section. This can be done with a special directive if the target supports
172 /// it (e.g. cygwin) or by emitting it as an offset from a label at the start
175 /// SectionLabel is a temporary label emitted at the start of the section that
177 void AsmPrinter::EmitSectionOffset(const MCSymbol
*Label
,
178 const MCSymbol
*SectionLabel
) const {
179 // On COFF targets, we have to emit the special .secrel32 directive.
180 if (const char *SecOffDir
= MAI
->getDwarfSectionOffsetDirective()) {
182 OutStreamer
.EmitRawText(SecOffDir
+ Twine(Label
->getName()));
186 // Get the section that we're referring to, based on SectionLabel.
187 const MCSection
&Section
= SectionLabel
->getSection();
189 // If Label has already been emitted, verify that it is in the same section as
190 // section label for sanity.
191 assert((!Label
->isInSection() || &Label
->getSection() == &Section
) &&
192 "Section offset using wrong section base for label");
194 // If the section in question will end up with an address of 0 anyway, we can
195 // just emit an absolute reference to save a relocation.
196 if (Section
.isBaseAddressKnownZero()) {
197 OutStreamer
.EmitSymbolValue(Label
, 4, 0/*AddrSpace*/);
201 // Otherwise, emit it as a label difference from the start of the section.
202 EmitLabelDifference(Label
, SectionLabel
, 4);
205 //===----------------------------------------------------------------------===//
206 // Dwarf Lowering Routines
207 //===----------------------------------------------------------------------===//
210 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
212 void AsmPrinter::EmitFrameMoves(const std::vector
<MachineMove
> &Moves
,
213 MCSymbol
*BaseLabel
, bool isEH
) const {
214 const TargetRegisterInfo
*RI
= TM
.getRegisterInfo();
216 int stackGrowth
= TM
.getTargetData()->getPointerSize();
217 if (TM
.getFrameLowering()->getStackGrowthDirection() !=
218 TargetFrameLowering::StackGrowsUp
)
221 for (unsigned i
= 0, N
= Moves
.size(); i
< N
; ++i
) {
222 const MachineMove
&Move
= Moves
[i
];
223 MCSymbol
*Label
= Move
.getLabel();
224 // Throw out move if the label is invalid.
225 if (Label
&& !Label
->isDefined()) continue; // Not emitted, in dead code.
227 const MachineLocation
&Dst
= Move
.getDestination();
228 const MachineLocation
&Src
= Move
.getSource();
230 // Advance row if new location.
231 if (BaseLabel
&& Label
) {
232 MCSymbol
*ThisSym
= Label
;
233 if (ThisSym
!= BaseLabel
) {
234 EmitCFAByte(dwarf::DW_CFA_advance_loc4
);
235 EmitLabelDifference(ThisSym
, BaseLabel
, 4);
241 if (Dst
.isReg() && Dst
.getReg() == MachineLocation::VirtualFP
) {
242 assert(!Src
.isReg() && "Machine move not supported yet.");
244 if (Src
.getReg() == MachineLocation::VirtualFP
) {
245 EmitCFAByte(dwarf::DW_CFA_def_cfa_offset
);
247 EmitCFAByte(dwarf::DW_CFA_def_cfa
);
248 EmitULEB128(RI
->getDwarfRegNum(Src
.getReg(), isEH
), "Register");
251 EmitULEB128(-Src
.getOffset(), "Offset");
255 if (Src
.isReg() && Src
.getReg() == MachineLocation::VirtualFP
) {
256 assert(Dst
.isReg() && "Machine move not supported yet.");
257 EmitCFAByte(dwarf::DW_CFA_def_cfa_register
);
258 EmitULEB128(RI
->getDwarfRegNum(Dst
.getReg(), isEH
), "Register");
262 unsigned Reg
= RI
->getDwarfRegNum(Src
.getReg(), isEH
);
263 int Offset
= Dst
.getOffset() / stackGrowth
;
266 EmitCFAByte(dwarf::DW_CFA_offset_extended_sf
);
267 EmitULEB128(Reg
, "Reg");
268 EmitSLEB128(Offset
, "Offset");
269 } else if (Reg
< 64) {
270 EmitCFAByte(dwarf::DW_CFA_offset
+ Reg
);
271 EmitULEB128(Offset
, "Offset");
273 EmitCFAByte(dwarf::DW_CFA_offset_extended
);
274 EmitULEB128(Reg
, "Reg");
275 EmitULEB128(Offset
, "Offset");
280 /// EmitFrameMoves - Emit frame instructions to describe the layout of the
282 void AsmPrinter::EmitCFIFrameMoves(const std::vector
<MachineMove
> &Moves
) const {
283 const TargetRegisterInfo
*RI
= TM
.getRegisterInfo();
285 for (unsigned i
= 0, N
= Moves
.size(); i
< N
; ++i
) {
286 const MachineMove
&Move
= Moves
[i
];
287 MCSymbol
*Label
= Move
.getLabel();
288 // Throw out move if the label is invalid.
289 if (Label
&& !Label
->isDefined()) continue; // Not emitted, in dead code.
291 const MachineLocation
&Dst
= Move
.getDestination();
292 const MachineLocation
&Src
= Move
.getSource();
295 if (Dst
.isReg() && Dst
.getReg() == MachineLocation::VirtualFP
) {
296 assert(!Src
.isReg() && "Machine move not supported yet.");
298 if (Src
.getReg() == MachineLocation::VirtualFP
) {
299 OutStreamer
.EmitCFIDefCfaOffset(-Src
.getOffset());
301 assert("Machine move not supported yet");
304 } else if (Src
.isReg() && Src
.getReg() == MachineLocation::VirtualFP
) {
305 assert(Dst
.isReg() && "Machine move not supported yet.");
306 OutStreamer
.EmitCFIDefCfaRegister(RI
->getDwarfRegNum(Dst
.getReg(), true));
308 assert(!Dst
.isReg() && "Machine move not supported yet.");
309 OutStreamer
.EmitCFIOffset(RI
->getDwarfRegNum(Src
.getReg(), true),