llvm.org GIT mirror llvm / f89325d
Debug info: Factor out the creation of DWARF expressions from AsmPrinter into a new class DwarfExpression that can be shared between AsmPrinter and DwarfUnit. This is the first step towards unifying the two entirely redundant implementations of dwarf expression emission in DwarfUnit and AsmPrinter. Almost no functional change — Testcases were updated because asm comments that used to be on two lines now appear on the same line, which is actually preferable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225706 91177308-0d34-0410-b5e6-96231b3b80d8 Adrian Prantl 5 years ago
7 changed file(s) with 256 addition(s) and 145 deletion(s). Raw diff Collapse all Expand all
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "ByteStreamer.h"
14 #include "DwarfExpression.h"
1415 #include "llvm/CodeGen/AsmPrinter.h"
15 #include "llvm/ADT/SmallBitVector.h"
1616 #include "llvm/ADT/Twine.h"
1717 #include "llvm/IR/DataLayout.h"
1818 #include "llvm/MC/MCAsmInfo.h"
3030 using namespace llvm;
3131
3232 #define DEBUG_TYPE "asm-printer"
33
34 /// DwarfExpression implementation for .debug_loc entries.
35 class DebugLocDwarfExpression : public DwarfExpression {
36 ByteStreamer &BS;
37 public:
38 DebugLocDwarfExpression(TargetMachine &TM, ByteStreamer &BS)
39 : DwarfExpression(TM), BS(BS) {}
40
41 void EmitOp(uint8_t Op, const char* Comment) override;
42 void EmitSigned(int Value) override;
43 void EmitUnsigned(unsigned Value) override;
44 };
45
46 void DebugLocDwarfExpression::EmitOp(uint8_t Op, const char* Comment) {
47 BS.EmitInt8(Op, Comment
48 ? Twine(Comment)+Twine(" ")+Twine(dwarf::OperationEncodingString(Op))
49 : dwarf::OperationEncodingString(Op));
50 }
51 void DebugLocDwarfExpression::EmitSigned(int Value) {
52 BS.EmitSLEB128(Value, Twine(Value));
53 }
54 void DebugLocDwarfExpression::EmitUnsigned(unsigned Value) {
55 BS.EmitULEB128(Value, Twine(Value));
56 }
57
3358
3459 //===----------------------------------------------------------------------===//
3560 // Dwarf Emission Helper Routines
186211 EmitLabelDifference(Label, SectionLabel, 4);
187212 }
188213
189 /// Emit a dwarf register operation.
190 static void emitDwarfRegOp(ByteStreamer &Streamer, int Reg) {
191 assert(Reg >= 0);
192 if (Reg < 32) {
193 Streamer.EmitInt8(dwarf::DW_OP_reg0 + Reg,
194 dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
195 } else {
196 Streamer.EmitInt8(dwarf::DW_OP_regx, "DW_OP_regx");
197 Streamer.EmitULEB128(Reg, Twine(Reg));
198 }
199 }
200
201 /// Emit an (double-)indirect dwarf register operation.
202 static void emitDwarfRegOpIndirect(ByteStreamer &Streamer, int Reg, int Offset,
203 bool Deref) {
204 assert(Reg >= 0);
205 if (Reg < 32) {
206 Streamer.EmitInt8(dwarf::DW_OP_breg0 + Reg,
207 dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
208 } else {
209 Streamer.EmitInt8(dwarf::DW_OP_bregx, "DW_OP_bregx");
210 Streamer.EmitULEB128(Reg, Twine(Reg));
211 }
212 Streamer.EmitSLEB128(Offset);
213 if (Deref)
214 Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
215 }
216
217 void AsmPrinter::EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits,
218 unsigned OffsetInBits) const {
219 assert(SizeInBits > 0 && "piece has size zero");
220 const unsigned SizeOfByte = 8;
221 if (OffsetInBits > 0 || SizeInBits % SizeOfByte) {
222 Streamer.EmitInt8(dwarf::DW_OP_bit_piece, "DW_OP_bit_piece");
223 Streamer.EmitULEB128(SizeInBits, Twine(SizeInBits));
224 Streamer.EmitULEB128(OffsetInBits, Twine(OffsetInBits));
225 } else {
226 Streamer.EmitInt8(dwarf::DW_OP_piece, "DW_OP_piece");
227 unsigned ByteSize = SizeInBits / SizeOfByte;
228 Streamer.EmitULEB128(ByteSize, Twine(ByteSize));
229 }
230 }
231
232 /// Emit a shift-right dwarf expression.
233 static void emitDwarfOpShr(ByteStreamer &Streamer,
234 unsigned ShiftBy) {
235 Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu");
236 Streamer.EmitULEB128(ShiftBy);
237 Streamer.EmitInt8(dwarf::DW_OP_shr, "DW_OP_shr");
238 }
239
240214 // Some targets do not provide a DWARF register number for every
241215 // register. This function attempts to emit a DWARF register by
242216 // emitting a piece of a super-register or by piecing together
246220 unsigned PieceSizeInBits,
247221 unsigned PieceOffsetInBits) const {
248222 assert(MLoc.isReg() && "MLoc must be a register");
249 const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo();
250 int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
251
252 // If this is a valid register number, emit it.
253 if (Reg >= 0) {
254 emitDwarfRegOp(Streamer, Reg);
255 EmitDwarfOpPiece(Streamer, PieceSizeInBits, PieceOffsetInBits);
256 return;
257 }
258
259 // Walk up the super-register chain until we find a valid number.
260 // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0.
261 for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
262 Reg = TRI->getDwarfRegNum(*SR, false);
263 if (Reg >= 0) {
264 unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg());
265 unsigned Size = TRI->getSubRegIdxSize(Idx);
266 unsigned RegOffset = TRI->getSubRegIdxOffset(Idx);
267 OutStreamer.AddComment("super-register");
268 emitDwarfRegOp(Streamer, Reg);
269 if (PieceOffsetInBits == RegOffset) {
270 EmitDwarfOpPiece(Streamer, Size, RegOffset);
271 } else {
272 // If this is part of a variable in a sub-register at a
273 // non-zero offset, we need to manually shift the value into
274 // place, since the DW_OP_piece describes the part of the
275 // variable, not the position of the subregister.
276 if (RegOffset)
277 emitDwarfOpShr(Streamer, RegOffset);
278 EmitDwarfOpPiece(Streamer, Size, PieceOffsetInBits);
279 }
280 return;
281 }
282 }
283
284 // Otherwise, attempt to find a covering set of sub-register numbers.
285 // For example, Q0 on ARM is a composition of D0+D1.
286 //
287 // Keep track of the current position so we can emit the more
288 // efficient DW_OP_piece.
289 unsigned CurPos = PieceOffsetInBits;
290 // The size of the register in bits, assuming 8 bits per byte.
291 unsigned RegSize = TRI->getMinimalPhysRegClass(MLoc.getReg())->getSize() * 8;
292 // Keep track of the bits in the register we already emitted, so we
293 // can avoid emitting redundant aliasing subregs.
294 SmallBitVector Coverage(RegSize, false);
295 for (MCSubRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
296 unsigned Idx = TRI->getSubRegIndex(MLoc.getReg(), *SR);
297 unsigned Size = TRI->getSubRegIdxSize(Idx);
298 unsigned Offset = TRI->getSubRegIdxOffset(Idx);
299 Reg = TRI->getDwarfRegNum(*SR, false);
300
301 // Intersection between the bits we already emitted and the bits
302 // covered by this subregister.
303 SmallBitVector Intersection(RegSize, false);
304 Intersection.set(Offset, Offset + Size);
305 Intersection ^= Coverage;
306
307 // If this sub-register has a DWARF number and we haven't covered
308 // its range, emit a DWARF piece for it.
309 if (Reg >= 0 && Intersection.any()) {
310 OutStreamer.AddComment("sub-register");
311 emitDwarfRegOp(Streamer, Reg);
312 EmitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset);
313 CurPos = Offset + Size;
314
315 // Mark it as emitted.
316 Coverage.set(Offset, Offset + Size);
317 }
318 }
319
320 if (CurPos == PieceOffsetInBits) {
321 // FIXME: We have no reasonable way of handling errors in here.
322 Streamer.EmitInt8(dwarf::DW_OP_nop,
323 "nop (could not find a dwarf register number)");
324 }
223 DebugLocDwarfExpression Expr(TM, Streamer);
224 Expr.AddMachineRegPiece(MLoc.getReg(), PieceSizeInBits, PieceOffsetInBits);
225 }
226
227 void AsmPrinter::EmitDwarfOpPiece(ByteStreamer &Streamer,
228 unsigned PieceSizeInBits,
229 unsigned PieceOffsetInBits) const {
230 DebugLocDwarfExpression Expr(TM, Streamer);
231 Expr.AddOpPiece(PieceSizeInBits, PieceOffsetInBits);
325232 }
326233
327234 /// EmitDwarfRegOp - Emit dwarf register operation.
328235 void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer,
329236 const MachineLocation &MLoc,
330237 bool Indirect) const {
238 DebugLocDwarfExpression Expr(TM, Streamer);
331239 const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo();
332240 int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
333241 if (Reg < 0) {
334242 // We assume that pointers are always in an addressable register.
335 if (Indirect || MLoc.isIndirect()) {
243 if (Indirect || MLoc.isIndirect())
336244 // FIXME: We have no reasonable way of handling errors in here. The
337245 // caller might be in the middle of a dwarf expression. We should
338246 // probably assert that Reg >= 0 once debug info generation is more
339247 // mature.
340 Streamer.EmitInt8(dwarf::DW_OP_nop,
341 "nop (invalid dwarf register number for indirect loc)");
342 return;
343 }
248 return Expr.EmitOp(dwarf::DW_OP_nop,
249 "nop (could not find a dwarf register number)");
344250
345251 // Attempt to find a valid super- or sub-register.
346 return EmitDwarfRegOpPiece(Streamer, MLoc);
252 return Expr.AddMachineRegPiece(MLoc.getReg());
347253 }
348254
349255 if (MLoc.isIndirect())
350 emitDwarfRegOpIndirect(Streamer, Reg, MLoc.getOffset(), Indirect);
256 Expr.AddRegIndirect(Reg, MLoc.getOffset(), Indirect);
351257 else if (Indirect)
352 emitDwarfRegOpIndirect(Streamer, Reg, 0, false);
258 Expr.AddRegIndirect(Reg, 0, false);
353259 else
354 emitDwarfRegOp(Streamer, Reg);
260 Expr.AddReg(Reg);
355261 }
356262
357263 //===----------------------------------------------------------------------===//
1010 DwarfCFIException.cpp
1111 DwarfCompileUnit.cpp
1212 DwarfDebug.cpp
13 DwarfExpression.cpp
1314 DwarfFile.cpp
1415 DwarfStringPool.cpp
1516 DwarfUnit.cpp
0 //===-- llvm/CodeGen/DwarfExpression.cpp - Dwarf Debug Framework ----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for writing dwarf debug info into asm files.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "DwarfExpression.h"
14 #include "llvm/ADT/SmallBitVector.h"
15 #include "llvm/Support/Dwarf.h"
16 #include "llvm/Target/TargetMachine.h"
17 #include "llvm/Target/TargetRegisterInfo.h"
18 #include "llvm/Target/TargetSubtargetInfo.h"
19
20
21 using namespace llvm;
22
23 void DwarfExpression::AddReg(int DwarfReg, const char* Comment) {
24 assert(DwarfReg >= 0 && "invalid negative dwarf register number");
25 if (DwarfReg < 32) {
26 EmitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
27 } else {
28 EmitOp(dwarf::DW_OP_regx, Comment);
29 EmitUnsigned(DwarfReg);
30 }
31 }
32
33 void DwarfExpression::AddRegIndirect(int DwarfReg, int Offset, bool Deref) {
34 assert(DwarfReg >= 0 && "invalid negative dwarf register number");
35 if (DwarfReg < 32) {
36 EmitOp(dwarf::DW_OP_breg0 + DwarfReg);
37 } else {
38 EmitOp(dwarf::DW_OP_bregx);
39 EmitUnsigned(DwarfReg);
40 }
41 EmitSigned(Offset);
42 if (Deref)
43 EmitOp(dwarf::DW_OP_deref);
44 }
45
46 void DwarfExpression::AddOpPiece(unsigned SizeInBits,
47 unsigned OffsetInBits) {
48 assert(SizeInBits > 0 && "piece has size zero");
49 const unsigned SizeOfByte = 8;
50 if (OffsetInBits > 0 || SizeInBits % SizeOfByte) {
51 EmitOp(dwarf::DW_OP_bit_piece);
52 EmitUnsigned(SizeInBits);
53 EmitUnsigned(OffsetInBits);
54 } else {
55 EmitOp(dwarf::DW_OP_piece);
56 unsigned ByteSize = SizeInBits / SizeOfByte;
57 EmitUnsigned(ByteSize);
58 }
59 }
60
61 void DwarfExpression::AddShr(unsigned ShiftBy) {
62 EmitOp(dwarf::DW_OP_constu);
63 EmitUnsigned(ShiftBy);
64 EmitOp(dwarf::DW_OP_shr);
65 }
66
67 void DwarfExpression::AddMachineRegPiece(unsigned MachineReg,
68 unsigned PieceSizeInBits,
69 unsigned PieceOffsetInBits) {
70 const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo();
71 int Reg = TRI->getDwarfRegNum(MachineReg, false);
72
73 // If this is a valid register number, emit it.
74 if (Reg >= 0) {
75 AddReg(Reg);
76 AddOpPiece(PieceSizeInBits, PieceOffsetInBits);
77 return;
78 }
79
80 // Walk up the super-register chain until we find a valid number.
81 // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0.
82 for (MCSuperRegIterator SR(MachineReg, TRI); SR.isValid(); ++SR) {
83 Reg = TRI->getDwarfRegNum(*SR, false);
84 if (Reg >= 0) {
85 unsigned Idx = TRI->getSubRegIndex(*SR, MachineReg);
86 unsigned Size = TRI->getSubRegIdxSize(Idx);
87 unsigned RegOffset = TRI->getSubRegIdxOffset(Idx);
88 AddReg(Reg, "super-register");
89 if (PieceOffsetInBits == RegOffset) {
90 AddOpPiece(Size, RegOffset);
91 } else {
92 // If this is part of a variable in a sub-register at a
93 // non-zero offset, we need to manually shift the value into
94 // place, since the DW_OP_piece describes the part of the
95 // variable, not the position of the subregister.
96 if (RegOffset)
97 AddShr(RegOffset);
98 AddOpPiece(Size, PieceOffsetInBits);
99 }
100 return;
101 }
102 }
103
104 // Otherwise, attempt to find a covering set of sub-register numbers.
105 // For example, Q0 on ARM is a composition of D0+D1.
106 //
107 // Keep track of the current position so we can emit the more
108 // efficient DW_OP_piece.
109 unsigned CurPos = PieceOffsetInBits;
110 // The size of the register in bits, assuming 8 bits per byte.
111 unsigned RegSize = TRI->getMinimalPhysRegClass(MachineReg)->getSize() * 8;
112 // Keep track of the bits in the register we already emitted, so we
113 // can avoid emitting redundant aliasing subregs.
114 SmallBitVector Coverage(RegSize, false);
115 for (MCSubRegIterator SR(MachineReg, TRI); SR.isValid(); ++SR) {
116 unsigned Idx = TRI->getSubRegIndex(MachineReg, *SR);
117 unsigned Size = TRI->getSubRegIdxSize(Idx);
118 unsigned Offset = TRI->getSubRegIdxOffset(Idx);
119 Reg = TRI->getDwarfRegNum(*SR, false);
120
121 // Intersection between the bits we already emitted and the bits
122 // covered by this subregister.
123 SmallBitVector Intersection(RegSize, false);
124 Intersection.set(Offset, Offset + Size);
125 Intersection ^= Coverage;
126
127 // If this sub-register has a DWARF number and we haven't covered
128 // its range, emit a DWARF piece for it.
129 if (Reg >= 0 && Intersection.any()) {
130 AddReg(Reg, "sub-register");
131 AddOpPiece(Size, Offset == CurPos ? 0 : Offset);
132 CurPos = Offset + Size;
133
134 // Mark it as emitted.
135 Coverage.set(Offset, Offset + Size);
136 }
137 }
138
139 if (CurPos == PieceOffsetInBits)
140 // FIXME: We have no reasonable way of handling errors in here.
141 EmitOp(dwarf::DW_OP_nop, "nop (could not find a dwarf register number)");
142 }
0 //===-- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ---*- C++ -*--===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for writing dwarf compile unit.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
14 #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
15
16 #include "llvm/Support/DataTypes.h"
17
18 namespace llvm {
19
20 class TargetMachine;
21
22 /// Base class containing the logic for constructing DWARF expressions
23 /// independently of whether they are emitted into a DIE or into a .debug_loc
24 /// entry.
25 class DwarfExpression {
26 TargetMachine &TM;
27 public:
28 DwarfExpression(TargetMachine &TM) : TM(TM) {}
29
30 virtual void EmitOp(uint8_t Op, const char* Comment = nullptr) = 0;
31 virtual void EmitSigned(int Value) = 0;
32 virtual void EmitUnsigned(unsigned Value) = 0;
33 /// Emit a dwarf register operation.
34 void AddReg(int DwarfReg, const char* Comment = nullptr);
35 /// Emit an (double-)indirect dwarf register operation.
36 void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false);
37
38 /// Emit a dwarf register operation for describing
39 /// - a small value occupying only part of a register or
40 /// - a register representing only part of a value.
41 void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
42 /// Emit a shift-right dwarf expression.
43 void AddShr(unsigned ShiftBy);
44
45 /// \brief Emit a partial DWARF register operation.
46 /// \param MLoc the register
47 /// \param PieceSize size and
48 /// \param PieceOffset offset of the piece in bits, if this is one
49 /// piece of an aggregate value.
50 ///
51 /// If size and offset is zero an operation for the entire
52 /// register is emitted: Some targets do not provide a DWARF
53 /// register number for every register. If this is the case, this
54 /// function will attempt to emit a DWARF register by emitting a
55 /// piece of a super-register or by piecing together multiple
56 /// subregisters that alias the register.
57 void AddMachineRegPiece(unsigned MachineReg,
58 unsigned PieceSizeInBits = 0,
59 unsigned PieceOffsetInBits = 0);
60 };
61
62 }
63
64 #endif
11 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
22 target triple = "thumbv7-apple-macosx10.6.7"
33
4 ;CHECK: sub-register
5 ;CHECK-NEXT: DW_OP_regx
4 ;CHECK: sub-register DW_OP_regx
65 ;CHECK-NEXT: ascii
76 ;CHECK-NEXT: DW_OP_piece
87 ;CHECK-NEXT: byte 8
9 ;CHECK-NEXT: sub-register
10 ;CHECK-NEXT: DW_OP_regx
8 ;CHECK-NEXT: sub-register DW_OP_regx
119 ;CHECK-NEXT: ascii
1210 ;CHECK-NEXT: DW_OP_piece
1311 ;CHECK-NEXT: byte 8
0 ; RUN: llc < %s - | FileCheck %s
11 ; Radar 9309221
22 ; Test dwarf reg no for s16
3 ;CHECK: super-register
4 ;CHECK-NEXT: DW_OP_regx
3 ;CHECK: super-register DW_OP_regx
54 ;CHECK-NEXT: ascii
65 ;CHECK-NEXT: DW_OP_piece
76 ;CHECK-NEXT: 4
22 ; We are testing that a value in a 16 bit register gets reported as
33 ; being in its superregister.
44
5 ; CHECK: .byte 80 # super-register
6 ; CHECK-NEXT: # DW_OP_reg0
5 ; CHECK: .byte 80 # super-register DW_OP_reg0
76 ; CHECK-NEXT: .byte 147 # DW_OP_piece
87 ; CHECK-NEXT: .byte 2 # 2
98