blob: 333cf546275cea525f573bdde9b2c4c05081a18e [file] [log] [blame]
Bill Wendlingbbee8c92009-05-15 00:11:17 +00001//===--- lib/CodeGen/DwarfPrinter.cpp - Dwarf Printer ---------------------===//
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// Emit general DWARF directives.
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +000011//
Bill Wendlingbbee8c92009-05-15 00:11:17 +000012//===----------------------------------------------------------------------===//
13
14#include "DwarfPrinter.h"
15#include "llvm/Module.h"
16#include "llvm/CodeGen/AsmPrinter.h"
17#include "llvm/CodeGen/MachineFrameInfo.h"
David Greene18938f92009-08-19 21:59:18 +000018#include "llvm/CodeGen/MachineFunction.h"
Bill Wendlingbbee8c92009-05-15 00:11:17 +000019#include "llvm/CodeGen/MachineModuleInfo.h"
Chris Lattner621c44d2009-08-22 20:48:53 +000020#include "llvm/MC/MCAsmInfo.h"
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +000021#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCExpr.h"
Chris Lattnerd705acf2010-01-22 22:38:16 +000023#include "llvm/MC/MCStreamer.h"
Chris Lattner41e330f2010-01-16 18:50:28 +000024#include "llvm/MC/MCSymbol.h"
Bill Wendlingbbee8c92009-05-15 00:11:17 +000025#include "llvm/Target/TargetData.h"
26#include "llvm/Target/TargetFrameInfo.h"
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +000027#include "llvm/Target/TargetLoweringObjectFile.h"
Bill Wendlingbbee8c92009-05-15 00:11:17 +000028#include "llvm/Target/TargetRegisterInfo.h"
Chris Lattner017c7f92010-04-04 18:06:11 +000029#include "llvm/Target/TargetMachine.h"
Chris Lattnerf5377682009-08-24 03:52:50 +000030#include "llvm/Support/Dwarf.h"
31#include "llvm/Support/ErrorHandling.h"
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +000032#include "llvm/ADT/SmallString.h"
Bill Wendlingbbee8c92009-05-15 00:11:17 +000033using namespace llvm;
34
Chris Lattner75e113c2010-04-04 07:48:20 +000035DwarfPrinter::DwarfPrinter(AsmPrinter *A)
36: Asm(A), MAI(A->MAI), TD(Asm->TM.getTargetData()),
Bill Wendlingbbee8c92009-05-15 00:11:17 +000037 RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL),
Chris Lattner819669a2010-03-09 00:00:15 +000038 SubprogramCount(0) {}
Bill Wendlingbbee8c92009-05-15 00:11:17 +000039
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +000040/// SizeOfEncodedValue - Return the size of the encoding in bytes.
41unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const {
42 if (Encoding == dwarf::DW_EH_PE_omit)
43 return 0;
44
45 switch (Encoding & 0x07) {
46 case dwarf::DW_EH_PE_absptr:
47 return TD->getPointerSize();
48 case dwarf::DW_EH_PE_udata2:
49 return 2;
50 case dwarf::DW_EH_PE_udata4:
51 return 4;
52 case dwarf::DW_EH_PE_udata8:
53 return 8;
54 }
55
56 assert(0 && "Invalid encoded value.");
57 return 0;
58}
59
Chris Lattnerd705acf2010-01-22 22:38:16 +000060static const char *DecodeDWARFEncoding(unsigned Encoding) {
61 switch (Encoding) {
62 case dwarf::DW_EH_PE_absptr: return "absptr";
63 case dwarf::DW_EH_PE_omit: return "omit";
64 case dwarf::DW_EH_PE_pcrel: return "pcrel";
65 case dwarf::DW_EH_PE_udata4: return "udata4";
66 case dwarf::DW_EH_PE_udata8: return "udata8";
67 case dwarf::DW_EH_PE_sdata4: return "sdata4";
68 case dwarf::DW_EH_PE_sdata8: return "sdata8";
69 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4";
70 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4";
71 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8";
72 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8";
73 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4:
74 return "indirect pcrel udata4";
75 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4:
76 return "indirect pcrel sdata4";
77 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8:
78 return "indirect pcrel udata8";
79 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8:
80 return "indirect pcrel sdata8";
81 }
82
83 return "<unknown encoding>";
84}
85
86/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
87/// encoding. If verbose assembly output is enabled, we output comments
88/// describing the encoding. Desc is an optional string saying what the
89/// encoding is specifying (e.g. "LSDA").
90void DwarfPrinter::EmitEncodingByte(unsigned Val, const char *Desc) {
Chris Lattner97c69b72010-04-04 18:52:31 +000091 if (Asm->isVerbose()) {
Chris Lattnerd705acf2010-01-22 22:38:16 +000092 if (Desc != 0)
93 Asm->OutStreamer.AddComment(Twine(Desc)+" Encoding = " +
94 Twine(DecodeDWARFEncoding(Val)));
95 else
96 Asm->OutStreamer.AddComment(Twine("Encoding = ") +
97 DecodeDWARFEncoding(Val));
98 }
99
100 Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
101}
102
Chris Lattnerab4cf952010-01-22 23:40:08 +0000103/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
104void DwarfPrinter::EmitCFAByte(unsigned Val) {
Chris Lattner97c69b72010-04-04 18:52:31 +0000105 if (Asm->isVerbose()) {
Chris Lattnerab4cf952010-01-22 23:40:08 +0000106 if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64)
107 Asm->OutStreamer.AddComment("DW_CFA_offset + Reg (" +
108 Twine(Val-dwarf::DW_CFA_offset) + ")");
109 else
110 Asm->OutStreamer.AddComment(dwarf::CallFrameString(Val));
111 }
112 Asm->OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/);
113}
114
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +0000115void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const {
116 const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
117
Chris Lattner8364cff2010-03-11 21:55:20 +0000118 const MCExpr *Exp = TLOF.getExprForDwarfReference(Sym, Asm->Mang,
119 Asm->MMI, Encoding,
Chris Lattnerd96b9ea2010-03-11 19:41:58 +0000120 Asm->OutStreamer);
Chris Lattnere77cd0f2010-03-10 00:09:21 +0000121 Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0);
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +0000122}
123
Chris Lattnerd317fef2010-03-08 23:58:37 +0000124void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +0000125 const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
126
Chris Lattnere77cd0f2010-03-10 00:09:21 +0000127 const MCExpr *Exp =
Chris Lattnerd96b9ea2010-03-11 19:41:58 +0000128 TLOF.getExprForDwarfGlobalReference(GV, Asm->Mang, Asm->MMI, Encoding,
129 Asm->OutStreamer);
Chris Lattnere77cd0f2010-03-10 00:09:21 +0000130 Asm->OutStreamer.EmitValue(Exp, SizeOfEncodedValue(Encoding), /*addrspace*/0);
Anton Korobeynikovd779bcb2010-02-15 22:35:59 +0000131}
132
Chris Lattner1fd01822010-01-26 20:20:43 +0000133/// EmitDifference - Emit the difference between two labels. If this assembler
134/// supports .set, we emit a .set of a temporary and then use it in the .word.
Chris Lattnerbe4c2fc2010-03-08 22:23:36 +0000135void DwarfPrinter::EmitDifference(const MCSymbol *TagHi, const MCSymbol *TagLo,
136 bool IsSmall) {
Chris Lattnerd317fef2010-03-08 23:58:37 +0000137 unsigned Size = IsSmall ? 4 : TD->getPointerSize();
138 Asm->EmitLabelDifference(TagHi, TagLo, Size);
Chris Lattnerbe4c2fc2010-03-08 22:23:36 +0000139}
140
Chris Lattnerbe4c2fc2010-03-08 22:23:36 +0000141void DwarfPrinter::EmitSectionOffset(const MCSymbol *Label,
142 const MCSymbol *Section,
Chris Lattnerf8bfa882010-03-08 23:23:25 +0000143 bool IsSmall, bool isEH) {
Chris Lattner84c27b22010-03-09 00:17:58 +0000144 bool isAbsolute;
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000145 if (isEH)
Chris Lattner84c27b22010-03-09 00:17:58 +0000146 isAbsolute = MAI->isAbsoluteEHSectionOffsets();
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000147 else
Chris Lattner84c27b22010-03-09 00:17:58 +0000148 isAbsolute = MAI->isAbsoluteDebugSectionOffsets();
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000149
Chris Lattner84c27b22010-03-09 00:17:58 +0000150 if (!isAbsolute)
Chris Lattnerf8bfa882010-03-08 23:23:25 +0000151 return EmitDifference(Label, Section, IsSmall);
152
Chris Lattner84c27b22010-03-09 00:17:58 +0000153 // On COFF targets, we have to emit the weird .secrel32 directive.
Chris Lattner33178492010-03-12 18:10:35 +0000154 if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) {
Chris Lattneree3b40f2010-03-10 01:04:13 +0000155 // FIXME: MCize.
Chris Lattner39db1962010-04-04 07:25:52 +0000156 Asm->OutStreamer.EmitRawText(SecOffDir + Twine(Label->getName()));
Chris Lattner33178492010-03-12 18:10:35 +0000157 } else {
Chris Lattner84c27b22010-03-09 00:17:58 +0000158 unsigned Size = IsSmall ? 4 : TD->getPointerSize();
Chris Lattner2ab0c442010-03-09 00:39:24 +0000159 Asm->OutStreamer.EmitSymbolValue(Label, Size, 0/*AddrSpace*/);
Chris Lattner84c27b22010-03-09 00:17:58 +0000160 }
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000161}
162
163/// EmitFrameMoves - Emit frame instructions to describe the layout of the
164/// frame.
Chris Lattnerdd4f4f82010-03-13 08:05:25 +0000165void DwarfPrinter::EmitFrameMoves(MCSymbol *BaseLabel,
Chris Lattnerb21f1042010-01-22 22:23:57 +0000166 const std::vector<MachineMove> &Moves,
167 bool isEH) {
Chris Lattner314e3362010-03-13 07:40:56 +0000168 int stackGrowth = TD->getPointerSize();
169 if (Asm->TM.getFrameInfo()->getStackGrowthDirection() !=
170 TargetFrameInfo::StackGrowsUp)
171 stackGrowth *= -1;
172
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000173 for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
174 const MachineMove &Move = Moves[i];
Chris Lattner6090b422010-03-14 08:12:40 +0000175 MCSymbol *Label = Move.getLabel();
Chris Lattner5e423432010-03-09 01:51:43 +0000176 // Throw out move if the label is invalid.
Chris Lattner6090b422010-03-14 08:12:40 +0000177 if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000178
179 const MachineLocation &Dst = Move.getDestination();
180 const MachineLocation &Src = Move.getSource();
181
182 // Advance row if new location.
Chris Lattner717599e2010-03-14 07:02:50 +0000183 if (BaseLabel && Label) {
Chris Lattner31ae74d2010-03-14 02:20:58 +0000184 MCSymbol *ThisSym = Label;
Chris Lattnerdd4f4f82010-03-13 08:05:25 +0000185 if (ThisSym != BaseLabel) {
186 EmitCFAByte(dwarf::DW_CFA_advance_loc4);
187 EmitDifference(ThisSym, BaseLabel, true);
188 BaseLabel = ThisSym;
189 }
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000190 }
191
192 // If advancing cfa.
193 if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
194 if (!Src.isReg()) {
195 if (Src.getReg() == MachineLocation::VirtualFP) {
Chris Lattnerab4cf952010-01-22 23:40:08 +0000196 EmitCFAByte(dwarf::DW_CFA_def_cfa_offset);
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000197 } else {
Chris Lattnerab4cf952010-01-22 23:40:08 +0000198 EmitCFAByte(dwarf::DW_CFA_def_cfa);
Chris Lattner26be1c12010-04-04 19:09:29 +0000199 Asm->EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register");
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000200 }
201
202 int Offset = -Src.getOffset();
Chris Lattner26be1c12010-04-04 19:09:29 +0000203 Asm->EmitULEB128(Offset, "Offset");
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000204 } else {
Edwin Törökbd448e32009-07-14 16:55:14 +0000205 llvm_unreachable("Machine move not supported yet.");
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000206 }
207 } else if (Src.isReg() &&
208 Src.getReg() == MachineLocation::VirtualFP) {
209 if (Dst.isReg()) {
Chris Lattnerab4cf952010-01-22 23:40:08 +0000210 EmitCFAByte(dwarf::DW_CFA_def_cfa_register);
Chris Lattner26be1c12010-04-04 19:09:29 +0000211 Asm->EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register");
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000212 } else {
Edwin Törökbd448e32009-07-14 16:55:14 +0000213 llvm_unreachable("Machine move not supported yet.");
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000214 }
215 } else {
216 unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
217 int Offset = Dst.getOffset() / stackGrowth;
218
219 if (Offset < 0) {
Chris Lattnerab4cf952010-01-22 23:40:08 +0000220 EmitCFAByte(dwarf::DW_CFA_offset_extended_sf);
Chris Lattner26be1c12010-04-04 19:09:29 +0000221 Asm->EmitULEB128(Reg, "Reg");
222 Asm->EmitSLEB128(Offset, "Offset");
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000223 } else if (Reg < 64) {
Chris Lattnerab4cf952010-01-22 23:40:08 +0000224 EmitCFAByte(dwarf::DW_CFA_offset + Reg);
Chris Lattner26be1c12010-04-04 19:09:29 +0000225 Asm->EmitULEB128(Offset, "Offset");
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000226 } else {
Chris Lattnerab4cf952010-01-22 23:40:08 +0000227 EmitCFAByte(dwarf::DW_CFA_offset_extended);
Chris Lattner26be1c12010-04-04 19:09:29 +0000228 Asm->EmitULEB128(Reg, "Reg");
229 Asm->EmitULEB128(Offset, "Offset");
Bill Wendlingbbee8c92009-05-15 00:11:17 +0000230 }
231 }
232 }
233}