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
, 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 //===----------------------------------------------------------------------===//
209 /// EmitCFIFrameMove - Emit a frame instruction.
210 void AsmPrinter::EmitCFIFrameMove(const MachineMove
&Move
) const {
211 const TargetRegisterInfo
*RI
= TM
.getRegisterInfo();
213 const MachineLocation
&Dst
= Move
.getDestination();
214 const MachineLocation
&Src
= Move
.getSource();
217 if (Dst
.isReg() && Dst
.getReg() == MachineLocation::VirtualFP
) {
218 if (Src
.getReg() == MachineLocation::VirtualFP
) {
219 OutStreamer
.EmitCFIDefCfaOffset(-Src
.getOffset());
222 OutStreamer
.EmitCFIDefCfa(RI
->getDwarfRegNum(Src
.getReg(), true),
225 } else if (Src
.isReg() && Src
.getReg() == MachineLocation::VirtualFP
) {
226 assert(Dst
.isReg() && "Machine move not supported yet.");
227 OutStreamer
.EmitCFIDefCfaRegister(RI
->getDwarfRegNum(Dst
.getReg(), true));
229 assert(!Dst
.isReg() && "Machine move not supported yet.");
230 OutStreamer
.EmitCFIOffset(RI
->getDwarfRegNum(Src
.getReg(), true),