blob: c166946989954512d5907baac2ae186023ec06c1 [file] [log] [blame]
Chris Lattner7e1a8f82010-04-04 19:09:29 +00001//===-- 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//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "asm-printer"
15#include "llvm/CodeGen/AsmPrinter.h"
Evan Cheng2d286172011-07-18 22:29:13 +000016#include "llvm/MC/MachineLocation.h"
Chris Lattner7e1a8f82010-04-04 19:09:29 +000017#include "llvm/MC/MCAsmInfo.h"
Chris Lattner6189ed12010-04-04 23:25:33 +000018#include "llvm/MC/MCSection.h"
Chris Lattner7e1a8f82010-04-04 19:09:29 +000019#include "llvm/MC/MCStreamer.h"
Chris Lattner6189ed12010-04-04 23:25:33 +000020#include "llvm/MC/MCSymbol.h"
Chris Lattnerd2af7852010-04-04 20:20:50 +000021#include "llvm/Target/TargetData.h"
Anton Korobeynikov16c29b52011-01-10 12:39:04 +000022#include "llvm/Target/TargetFrameLowering.h"
Chris Lattnerd2af7852010-04-04 20:20:50 +000023#include "llvm/Target/TargetLoweringObjectFile.h"
24#include "llvm/Target/TargetMachine.h"
Chris Lattner02b86b92010-04-04 23:41:46 +000025#include "llvm/Target/TargetRegisterInfo.h"
Chris Lattner7e1a8f82010-04-04 19:09:29 +000026#include "llvm/ADT/Twine.h"
Chris Lattner7a101f42010-04-04 20:01:25 +000027#include "llvm/Support/Dwarf.h"
Chris Lattner7e1a8f82010-04-04 19:09:29 +000028using namespace llvm;
29
Chris Lattner02b86b92010-04-04 23:41:46 +000030//===----------------------------------------------------------------------===//
31// Dwarf Emission Helper Routines
32//===----------------------------------------------------------------------===//
33
Chris Lattner7e1a8f82010-04-04 19:09:29 +000034/// EmitSLEB128 - emit the specified signed leb128 value.
35void AsmPrinter::EmitSLEB128(int Value, const char *Desc) const {
36 if (isVerbose() && Desc)
37 OutStreamer.AddComment(Desc);
Chris Lattner7e1a8f82010-04-04 19:09:29 +000038
Benjamin Kramerc25c9082011-11-05 11:52:44 +000039 OutStreamer.EmitSLEB128IntValue(Value);
Chris Lattner7e1a8f82010-04-04 19:09:29 +000040}
41
42/// EmitULEB128 - emit the specified signed leb128 value.
43void AsmPrinter::EmitULEB128(unsigned Value, const char *Desc,
44 unsigned PadTo) const {
45 if (isVerbose() && Desc)
46 OutStreamer.AddComment(Desc);
Rafael Espindola73873452010-11-04 18:17:08 +000047
Benjamin Kramerc25c9082011-11-05 11:52:44 +000048 OutStreamer.EmitULEB128IntValue(Value, 0/*addrspace*/, PadTo);
Chris Lattner7e1a8f82010-04-04 19:09:29 +000049}
50
Chris Lattner7a101f42010-04-04 20:01:25 +000051/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
52void AsmPrinter::EmitCFAByte(unsigned Val) const {
53 if (isVerbose()) {
54 if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64)
55 OutStreamer.AddComment("DW_CFA_offset + Reg (" +
56 Twine(Val-dwarf::DW_CFA_offset) + ")");
57 else
58 OutStreamer.AddComment(dwarf::CallFrameString(Val));
59 }
60 OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
61}
62
Chris Lattnerca6190b2010-04-04 20:04:21 +000063static const char *DecodeDWARFEncoding(unsigned Encoding) {
64 switch (Encoding) {
65 case dwarf::DW_EH_PE_absptr: return "absptr";
66 case dwarf::DW_EH_PE_omit: return "omit";
67 case dwarf::DW_EH_PE_pcrel: return "pcrel";
68 case dwarf::DW_EH_PE_udata4: return "udata4";
69 case dwarf::DW_EH_PE_udata8: return "udata8";
70 case dwarf::DW_EH_PE_sdata4: return "sdata4";
71 case dwarf::DW_EH_PE_sdata8: return "sdata8";
72 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4";
73 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4";
74 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8";
75 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8";
76 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4:
77 return "indirect pcrel udata4";
78 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4:
79 return "indirect pcrel sdata4";
80 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8:
81 return "indirect pcrel udata8";
82 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8:
83 return "indirect pcrel sdata8";
84 }
85
86 return "<unknown encoding>";
87}
88
89
90/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
91/// encoding. If verbose assembly output is enabled, we output comments
92/// describing the encoding. Desc is an optional string saying what the
93/// encoding is specifying (e.g. "LSDA").
Chris Lattner02b86b92010-04-04 23:41:46 +000094void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const {
Chris Lattnerca6190b2010-04-04 20:04:21 +000095 if (isVerbose()) {
96 if (Desc != 0)
97 OutStreamer.AddComment(Twine(Desc)+" Encoding = " +
98 Twine(DecodeDWARFEncoding(Val)));
99 else
100 OutStreamer.AddComment(Twine("Encoding = ") +
101 DecodeDWARFEncoding(Val));
102 }
103
104 OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
105}
106
Chris Lattnerd2af7852010-04-04 20:20:50 +0000107/// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
108unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
109 if (Encoding == dwarf::DW_EH_PE_omit)
110 return 0;
111
112 switch (Encoding & 0x07) {
113 default: assert(0 && "Invalid encoded value.");
114 case dwarf::DW_EH_PE_absptr: return TM.getTargetData()->getPointerSize();
115 case dwarf::DW_EH_PE_udata2: return 2;
116 case dwarf::DW_EH_PE_udata4: return 4;
117 case dwarf::DW_EH_PE_udata8: return 8;
118 }
119}
120
121void AsmPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const {
122 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
123
124 const MCExpr *Exp =
Rafael Espindola4788c3e2011-04-20 03:08:09 +0000125 TLOF.getExprForDwarfReference(Sym, Encoding, OutStreamer);
Rafael Espindola0bbe0b42010-12-06 17:27:56 +0000126 OutStreamer.EmitAbsValue(Exp, GetSizeOfEncodedValue(Encoding));
Chris Lattnerd2af7852010-04-04 20:20:50 +0000127}
128
129void AsmPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{
130 const TargetLoweringObjectFile &TLOF = getObjFileLowering();
131
132 const MCExpr *Exp =
133 TLOF.getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, OutStreamer);
134 OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0);
135}
Chris Lattner6189ed12010-04-04 23:25:33 +0000136
137/// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its
138/// section. This can be done with a special directive if the target supports
139/// it (e.g. cygwin) or by emitting it as an offset from a label at the start
140/// of the section.
141///
142/// SectionLabel is a temporary label emitted at the start of the section that
143/// Label lives in.
144void AsmPrinter::EmitSectionOffset(const MCSymbol *Label,
145 const MCSymbol *SectionLabel) const {
146 // On COFF targets, we have to emit the special .secrel32 directive.
Rafael Espindola8f7d12c2011-12-17 01:14:52 +0000147 if (MAI->getDwarfSectionOffsetDirective()) {
148 OutStreamer.EmitCOFFSecRel32(Label);
Chris Lattner6189ed12010-04-04 23:25:33 +0000149 return;
150 }
151
152 // Get the section that we're referring to, based on SectionLabel.
153 const MCSection &Section = SectionLabel->getSection();
154
155 // If Label has already been emitted, verify that it is in the same section as
156 // section label for sanity.
157 assert((!Label->isInSection() || &Label->getSection() == &Section) &&
158 "Section offset using wrong section base for label");
159
Duncan Sandsba993462011-03-12 13:07:37 +0000160 // If the section in question will end up with an address of 0 anyway, we can
161 // just emit an absolute reference to save a relocation.
162 if (Section.isBaseAddressKnownZero()) {
163 OutStreamer.EmitSymbolValue(Label, 4, 0/*AddrSpace*/);
164 return;
165 }
166
Chris Lattner6189ed12010-04-04 23:25:33 +0000167 // Otherwise, emit it as a label difference from the start of the section.
168 EmitLabelDifference(Label, SectionLabel, 4);
169}
170
Chris Lattner02b86b92010-04-04 23:41:46 +0000171//===----------------------------------------------------------------------===//
172// Dwarf Lowering Routines
173//===----------------------------------------------------------------------===//
Chris Lattner6189ed12010-04-04 23:25:33 +0000174
Rafael Espindolaffa64082011-05-06 15:28:56 +0000175/// EmitCFIFrameMove - Emit a frame instruction.
Rafael Espindola126ae682011-04-15 20:32:03 +0000176void AsmPrinter::EmitCFIFrameMove(const MachineMove &Move) const {
177 const TargetRegisterInfo *RI = TM.getRegisterInfo();
178
179 const MachineLocation &Dst = Move.getDestination();
180 const MachineLocation &Src = Move.getSource();
181
182 // If advancing cfa.
183 if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
Rafael Espindola126ae682011-04-15 20:32:03 +0000184 if (Src.getReg() == MachineLocation::VirtualFP) {
185 OutStreamer.EmitCFIDefCfaOffset(-Src.getOffset());
186 } else {
Rafael Espindola126ae682011-04-15 20:32:03 +0000187 // Reg + Offset
Jim Grosbach2b6f7112011-05-20 21:23:17 +0000188 OutStreamer.EmitCFIDefCfa(RI->getDwarfRegNum(Src.getReg(), true),
189 Src.getOffset());
Rafael Espindola126ae682011-04-15 20:32:03 +0000190 }
191 } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) {
192 assert(Dst.isReg() && "Machine move not supported yet.");
193 OutStreamer.EmitCFIDefCfaRegister(RI->getDwarfRegNum(Dst.getReg(), true));
194 } else {
195 assert(!Dst.isReg() && "Machine move not supported yet.");
196 OutStreamer.EmitCFIOffset(RI->getDwarfRegNum(Src.getReg(), true),
Rafael Espindolab28d4f12011-04-26 03:58:56 +0000197 Dst.getOffset());
Rafael Espindola126ae682011-04-15 20:32:03 +0000198 }
199}