]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - opencl/llvm.git/blob - lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
Debug Info: Add a virtual destructor to DwarfExpression.
[opencl/llvm.git] / lib / CodeGen / AsmPrinter / AsmPrinterDwarf.cpp
1 //===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===//
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 // This file implements the Dwarf emissions parts of AsmPrinter.
11 //
12 //===----------------------------------------------------------------------===//
14 #include "ByteStreamer.h"
15 #include "DwarfExpression.h"
16 #include "llvm/CodeGen/AsmPrinter.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/IR/DataLayout.h"
19 #include "llvm/MC/MCAsmInfo.h"
20 #include "llvm/MC/MCSection.h"
21 #include "llvm/MC/MCStreamer.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/MC/MachineLocation.h"
24 #include "llvm/Support/Dwarf.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Target/TargetFrameLowering.h"
27 #include "llvm/Target/TargetLoweringObjectFile.h"
28 #include "llvm/Target/TargetMachine.h"
29 #include "llvm/Target/TargetRegisterInfo.h"
30 #include "llvm/Target/TargetSubtargetInfo.h"
31 using namespace llvm;
33 #define DEBUG_TYPE "asm-printer"
35 /// DwarfExpression implementation for .debug_loc entries.
36 class DebugLocDwarfExpression : public DwarfExpression {
37   ByteStreamer &BS;
38 public:
39   DebugLocDwarfExpression(TargetMachine &TM, ByteStreamer &BS)
40     : DwarfExpression(TM), BS(BS) {}
42   void EmitOp(uint8_t Op, const char* Comment) override;
43   void EmitSigned(int Value) override;
44   void EmitUnsigned(unsigned Value) override;
45   unsigned getFrameRegister() override {
46     llvm_unreachable("not available");
47   };
48 };
50 void DebugLocDwarfExpression::EmitOp(uint8_t Op, const char* Comment) {
51   BS.EmitInt8(Op, Comment
52     ? Twine(Comment)+" "+dwarf::OperationEncodingString(Op)
53     : dwarf::OperationEncodingString(Op));
54 }
55 void DebugLocDwarfExpression::EmitSigned(int Value) {
56   BS.EmitSLEB128(Value, Twine(Value));
57 }
58 void DebugLocDwarfExpression::EmitUnsigned(unsigned Value) {
59   BS.EmitULEB128(Value, Twine(Value));
60 }
63 //===----------------------------------------------------------------------===//
64 // Dwarf Emission Helper Routines
65 //===----------------------------------------------------------------------===//
67 /// EmitSLEB128 - emit the specified signed leb128 value.
68 void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
69   if (isVerbose() && Desc)
70     OutStreamer.AddComment(Desc);
72   OutStreamer.EmitSLEB128IntValue(Value);
73 }
75 /// EmitULEB128 - emit the specified signed leb128 value.
76 void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc,
77                              unsigned PadTo) const {
78   if (isVerbose() && Desc)
79     OutStreamer.AddComment(Desc);
81   OutStreamer.EmitULEB128IntValue(Value, PadTo);
82 }
84 /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
85 void AsmPrinter::EmitCFAByte(unsigned Val) const {
86   if (isVerbose()) {
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) + ")");
90     else
91       OutStreamer.AddComment(dwarf::CallFrameString(Val));
92   }
93   OutStreamer.EmitIntValue(Val, 1);
94 }
96 static const char *DecodeDWARFEncoding(unsigned Encoding) {
97   switch (Encoding) {
98   case dwarf::DW_EH_PE_absptr:
99     return "absptr";
100   case dwarf::DW_EH_PE_omit:
101     return "omit";
102   case dwarf::DW_EH_PE_pcrel:
103     return "pcrel";
104   case dwarf::DW_EH_PE_udata4:
105     return "udata4";
106   case dwarf::DW_EH_PE_udata8:
107     return "udata8";
108   case dwarf::DW_EH_PE_sdata4:
109     return "sdata4";
110   case dwarf::DW_EH_PE_sdata8:
111     return "sdata8";
112   case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
113     return "pcrel udata4";
114   case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
115     return "pcrel sdata4";
116   case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
117     return "pcrel udata8";
118   case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
119     return "pcrel sdata8";
120   case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4
121       :
122     return "indirect pcrel udata4";
123   case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
124       :
125     return "indirect pcrel sdata4";
126   case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8
127       :
128     return "indirect pcrel udata8";
129   case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8
130       :
131     return "indirect pcrel sdata8";
132   }
134   return "<unknown encoding>";
137 /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
138 /// encoding.  If verbose assembly output is enabled, we output comments
139 /// describing the encoding.  Desc is an optional string saying what the
140 /// encoding is specifying (e.g. "LSDA").
141 void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const {
142   if (isVerbose()) {
143     if (Desc)
144       OutStreamer.AddComment(Twine(Desc) + " Encoding = " +
145                              Twine(DecodeDWARFEncoding(Val)));
146     else
147       OutStreamer.AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val));
148   }
150   OutStreamer.EmitIntValue(Val, 1);
153 /// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
154 unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
155   if (Encoding == dwarf::DW_EH_PE_omit)
156     return 0;
158   switch (Encoding & 0x07) {
159   default:
160     llvm_unreachable("Invalid encoded value.");
161   case dwarf::DW_EH_PE_absptr:
162     return TM.getSubtargetImpl()->getDataLayout()->getPointerSize();
163   case dwarf::DW_EH_PE_udata2:
164     return 2;
165   case dwarf::DW_EH_PE_udata4:
166     return 4;
167   case dwarf::DW_EH_PE_udata8:
168     return 8;
169   }
172 void AsmPrinter::EmitTTypeReference(const GlobalValue *GV,
173                                     unsigned Encoding) const {
174   if (GV) {
175     const TargetLoweringObjectFile &TLOF = getObjFileLowering();
177     const MCExpr *Exp =
178         TLOF.getTTypeGlobalReference(GV, Encoding, *Mang, TM, MMI, OutStreamer);
179     OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding));
180   } else
181     OutStreamer.EmitIntValue(0, GetSizeOfEncodedValue(Encoding));
184 /// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its
185 /// section.  This can be done with a special directive if the target supports
186 /// it (e.g. cygwin) or by emitting it as an offset from a label at the start
187 /// of the section.
188 ///
189 /// SectionLabel is a temporary label emitted at the start of the section that
190 /// Label lives in.
191 void AsmPrinter::EmitSectionOffset(const MCSymbol *Label,
192                                    const MCSymbol *SectionLabel) const {
193   // On COFF targets, we have to emit the special .secrel32 directive.
194   if (MAI->needsDwarfSectionOffsetDirective()) {
195     OutStreamer.EmitCOFFSecRel32(Label);
196     return;
197   }
199   // Get the section that we're referring to, based on SectionLabel.
200   const MCSection &Section = SectionLabel->getSection();
202   // If Label has already been emitted, verify that it is in the same section as
203   // section label for sanity.
204   assert((!Label->isInSection() || &Label->getSection() == &Section) &&
205          "Section offset using wrong section base for label");
207   // If the section in question will end up with an address of 0 anyway, we can
208   // just emit an absolute reference to save a relocation.
209   if (Section.isBaseAddressKnownZero()) {
210     OutStreamer.EmitSymbolValue(Label, 4);
211     return;
212   }
214   // Otherwise, emit it as a label difference from the start of the section.
215   EmitLabelDifference(Label, SectionLabel, 4);
218 // Some targets do not provide a DWARF register number for every
219 // register.  This function attempts to emit a DWARF register by
220 // emitting a piece of a super-register or by piecing together
221 // multiple subregisters that alias the register.
222 void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer,
223                                      const MachineLocation &MLoc,
224                                      unsigned PieceSizeInBits,
225                                      unsigned PieceOffsetInBits) const {
226   assert(MLoc.isReg() && "MLoc must be a register");
227   DebugLocDwarfExpression Expr(TM, Streamer);
228   Expr.AddMachineRegPiece(MLoc.getReg(), PieceSizeInBits, PieceOffsetInBits);
231 void AsmPrinter::EmitDwarfOpPiece(ByteStreamer &Streamer,
232                                   unsigned PieceSizeInBits,
233                                   unsigned PieceOffsetInBits) const {
234   DebugLocDwarfExpression Expr(TM, Streamer);
235   Expr.AddOpPiece(PieceSizeInBits, PieceOffsetInBits);
238 /// EmitDwarfRegOp - Emit dwarf register operation.
239 void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer,
240                                 const MachineLocation &MLoc,
241                                 bool Indirect) const {
242   DebugLocDwarfExpression Expr(TM, Streamer);
243   const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo();
244   int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
245   if (Reg < 0) {
246     // We assume that pointers are always in an addressable register.
247     if (Indirect || MLoc.isIndirect())
248       // FIXME: We have no reasonable way of handling errors in here. The
249       // caller might be in the middle of a dwarf expression. We should
250       // probably assert that Reg >= 0 once debug info generation is more
251       // mature.
252     return Expr.EmitOp(dwarf::DW_OP_nop,
253                        "nop (could not find a dwarf register number)");
255     // Attempt to find a valid super- or sub-register.
256     return Expr.AddMachineRegPiece(MLoc.getReg());
257   }
259   if (MLoc.isIndirect())
260     Expr.AddRegIndirect(Reg, MLoc.getOffset(), Indirect);
261   else if (Indirect)
262     Expr.AddRegIndirect(Reg, 0, false);
263   else
264     Expr.AddReg(Reg);
267 //===----------------------------------------------------------------------===//
268 // Dwarf Lowering Routines
269 //===----------------------------------------------------------------------===//
271 void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
272   switch (Inst.getOperation()) {
273   default:
274     llvm_unreachable("Unexpected instruction");
275   case MCCFIInstruction::OpDefCfaOffset:
276     OutStreamer.EmitCFIDefCfaOffset(Inst.getOffset());
277     break;
278   case MCCFIInstruction::OpDefCfa:
279     OutStreamer.EmitCFIDefCfa(Inst.getRegister(), Inst.getOffset());
280     break;
281   case MCCFIInstruction::OpDefCfaRegister:
282     OutStreamer.EmitCFIDefCfaRegister(Inst.getRegister());
283     break;
284   case MCCFIInstruction::OpOffset:
285     OutStreamer.EmitCFIOffset(Inst.getRegister(), Inst.getOffset());
286     break;
287   case MCCFIInstruction::OpRegister:
288     OutStreamer.EmitCFIRegister(Inst.getRegister(), Inst.getRegister2());
289     break;
290   case MCCFIInstruction::OpWindowSave:
291     OutStreamer.EmitCFIWindowSave();
292     break;
293   case MCCFIInstruction::OpSameValue:
294     OutStreamer.EmitCFISameValue(Inst.getRegister());
295     break;
296   }