LLVM: lib/DebugInfo/LogicalView/Core/LVLocation.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
17
18using namespace llvm;
20
21#define DEBUG_TYPE "Location"
22
24
25
26
30
31 auto PrintRegisterInfo = [&](LVSmall Code) {
32
33
34
35 if (dwarf::DW_OP_lit0 <= Code && Code <= dwarf::DW_OP_lit31) {
36 Stream << format("lit%d", Code - dwarf::DW_OP_lit0);
37 return;
38 }
39
40
41
42
43 if (dwarf::DW_OP_breg0 <= Code && Code <= dwarf::DW_OP_breg31) {
45 Stream << format("breg%d+%d%s", Code - dwarf::DW_OP_breg0, Operands[0],
46 RegisterName.c_str());
47 return;
48 }
49
50
51
52
53 if (dwarf::DW_OP_reg0 <= Code && Code <= dwarf::DW_OP_reg31) {
55 Stream << format("reg%d%s", Code - dwarf::DW_OP_reg0,
56 RegisterName.c_str());
57 return;
58 }
59
62 };
63
64 switch (Opcode) {
65
66
67
68 case dwarf::DW_OP_addr:
69 Stream << "addr " << hexString(Operands[0]);
70 break;
71 case dwarf::DW_OP_constu:
72 case dwarf::DW_OP_const1u:
73 case dwarf::DW_OP_const2u:
74 case dwarf::DW_OP_const4u:
75 case dwarf::DW_OP_const8u:
76 Stream << "const_u " << unsigned(Operands[0]);
77 break;
78 case dwarf::DW_OP_consts:
79 case dwarf::DW_OP_const1s:
80 case dwarf::DW_OP_const2s:
81 case dwarf::DW_OP_const4s:
82 case dwarf::DW_OP_const8s:
83 Stream << "const_s " << int(Operands[0]);
84 break;
85 case dwarf::DW_OP_addrx:
86 Stream << "addrx " << unsigned(Operands[0]);
87 break;
88 case dwarf::DW_OP_constx:
89 Stream << "constx " << unsigned(Operands[0]);
90 break;
91 case dwarf::DW_OP_const_type:
92 Stream << "TODO: DW_OP_const_type";
93 break;
94
95
96
97
98 case dwarf::DW_OP_fbreg:
99 Stream << "fbreg " << int(Operands[0]);
100 break;
101 case dwarf::DW_OP_bregx: {
103 Stream << format("bregx %d%s+%d", Operands[0], RegisterName.c_str(),
104 unsigned(Operands[1]));
105 break;
106 }
107 case dwarf::DW_OP_regval_type: {
109 Stream << format("regval_type %d%s+%d", Operands[0], RegisterName.c_str(),
110 unsigned(Operands[1]));
111 break;
112 }
113
114
115
116
117 case dwarf::DW_OP_dup:
118 Stream << "dup";
119 break;
120 case dwarf::DW_OP_drop:
121 Stream << "drop";
122 break;
123 case dwarf::DW_OP_pick:
124 Stream << "pick " << unsigned(Operands[0]);
125 break;
126 case dwarf::DW_OP_over:
127 Stream << "over";
128 break;
129 case dwarf::DW_OP_swap:
130 Stream << "swap";
131 break;
132 case dwarf::DW_OP_rot:
133 Stream << "rot";
134 break;
135 case dwarf::DW_OP_deref:
136 Stream << "deref";
137 break;
138 case dwarf::DW_OP_deref_size:
139 Stream << "deref_size " << unsigned(Operands[0]);
140 break;
141 case dwarf::DW_OP_deref_type:
142 Stream << "deref_type " << unsigned(Operands[0]) << " DIE offset "
144 break;
145 case dwarf::DW_OP_xderef:
146 Stream << "xderef";
147 break;
148 case dwarf::DW_OP_xderef_size:
149 Stream << "xderef_size " << unsigned(Operands[0]);
150 break;
151 case dwarf::DW_OP_xderef_type:
152 Stream << "xderef_type " << unsigned(Operands[0]) << " DIE offset "
154 break;
155 case dwarf::DW_OP_push_object_address:
156 Stream << "push_object_address";
157 break;
158 case dwarf::DW_OP_form_tls_address:
159 Stream << "form_tls_address";
160 break;
161 case dwarf::DW_OP_call_frame_cfa:
162 Stream << "call_frame_cfa";
163 break;
164
165
166
167
168 case dwarf::DW_OP_abs:
169 Stream << "abs";
170 break;
171 case dwarf::DW_OP_and:
172 Stream << "and";
173 break;
174 case dwarf::DW_OP_div:
175 Stream << "div";
176 break;
177 case dwarf::DW_OP_minus:
178 Stream << "minus";
179 break;
180 case dwarf::DW_OP_mod:
181 Stream << "mod";
182 break;
183 case dwarf::DW_OP_mul:
184 Stream << "mul";
185 break;
186 case dwarf::DW_OP_neg:
187 Stream << "neg";
188 break;
189 case dwarf::DW_OP_not:
190 Stream << "not";
191 break;
192 case dwarf::DW_OP_or:
193 Stream << "or";
194 break;
195 case dwarf::DW_OP_plus:
196 Stream << "plus";
197 break;
198 case dwarf::DW_OP_plus_uconst:
199 Stream << "plus_uconst " << unsigned(Operands[0]);
200 break;
201 case dwarf::DW_OP_shl:
202 Stream << "shl";
203 break;
204 case dwarf::DW_OP_shr:
205 Stream << "shr";
206 break;
207 case dwarf::DW_OP_shra:
208 Stream << "shra";
209 break;
210 case dwarf::DW_OP_xor:
211 Stream << "xor";
212 break;
213
214
215
216
217 case dwarf::DW_OP_le:
218 Stream << "le";
219 break;
220 case dwarf::DW_OP_ge:
221 Stream << "ge";
222 break;
223 case dwarf::DW_OP_eq:
224 Stream << "eq";
225 break;
226 case dwarf::DW_OP_lt:
227 Stream << "lt";
228 break;
229 case dwarf::DW_OP_gt:
230 Stream << "gt";
231 break;
232 case dwarf::DW_OP_ne:
233 Stream << "ne";
234 break;
235 case dwarf::DW_OP_skip:
236 Stream << "skip " << signed(Operands[0]);
237 break;
238 case dwarf::DW_OP_bra:
239 Stream << "bra " << signed(Operands[0]);
240 break;
241 case dwarf::DW_OP_call2:
242 Stream << "call2 DIE offset " << hexString(Operands[0]);
243 break;
244 case dwarf::DW_OP_call4:
245 Stream << "call4 DIE offset " << hexString(Operands[0]);
246 break;
247 case dwarf::DW_OP_call_ref:
248 Stream << "call_ref DIE offset " << hexString(Operands[0]);
249 break;
250
251
252
253
254 case dwarf::DW_OP_convert:
255 Stream << "convert DIE offset " << hexString(Operands[0]);
256 break;
257 case dwarf::DW_OP_reinterpret:
258 Stream << "reinterpret DIE offset " << hexString(Operands[0]);
259 break;
260
261
262
263
264 case dwarf::DW_OP_nop:
265 Stream << "nop";
266 break;
267 case dwarf::DW_OP_entry_value:
268 Stream << "TODO: DW_OP_entry_value";
269 break;
270
271
272
273
274 case dwarf::DW_OP_regx:
276 break;
277
278
279
280
281 case dwarf::DW_OP_stack_value:
282 Stream << "stack_value";
283 break;
284 case dwarf::DW_OP_implicit_value:
285 Stream << "TODO: DW_OP_implicit_value";
286 break;
287 case dwarf::DW_OP_implicit_pointer:
288 Stream << "implicit_pointer DIE offset " << hexString(Operands[0]) << " "
289 << int(Operands[1]);
290 break;
291
292
293
294
295 case dwarf::DW_OP_piece:
296 Stream << "piece " << int(Operands[0]);
297 break;
298 case dwarf::DW_OP_bit_piece:
299 Stream << "bit_piece " << int(Operands[0]) << " offset "
300 << int(Operands[1]);
301 break;
302
303
304
305
306 case dwarf::DW_OP_GNU_entry_value:
307 Stream << "gnu_entry_value ";
308 PrintRegisterInfo(dwarf::DW_OP_reg0);
309 break;
310 case dwarf::DW_OP_GNU_push_tls_address:
311 Stream << "gnu_push_tls_address";
312 break;
313 case dwarf::DW_OP_GNU_addr_index:
314 Stream << "gnu_addr_index " << unsigned(Operands[0]);
315 break;
316 case dwarf::DW_OP_GNU_const_index:
317 Stream << "gnu_const_index " << unsigned(Operands[0]);
318 break;
319
320
321
322
324 Stream << "offset " << int(Operands[0]);
325 break;
326
327
328
329
331 Stream << "missing";
332 break;
333
334
335
336
337 default:
338 PrintRegisterInfo(Opcode);
339 break;
340 }
341
343}
344
345
346
350
351
353
354 switch (OperationCode) {
355
356 case codeview::SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:
357 Stream << "frame_pointer_rel " << int(Operands[0]);
358 break;
359 case codeview::SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
360 Stream << "frame_pointer_rel_full_scope " << int(Operands[0]);
361 break;
362
363
364 case codeview::SymbolKind::S_DEFRANGE_REGISTER:
366 break;
367 case codeview::SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:
368 Stream << "subfield_register "
370 break;
371
372
373 case codeview::SymbolKind::S_DEFRANGE_REGISTER_REL:
375 << " offset " << int(Operands[1]);
376 break;
377
378
379 case codeview::SymbolKind::S_DEFRANGE:
380 Stream << "frame " << int(Operands[0]);
381 break;
382 case codeview::SymbolKind::S_DEFRANGE_SUBFIELD:
383 Stream << "subfield " << int(Operands[0]);
384 break;
385
386 default:
387 Stream << format("#0x%02x: ", Opcode) << hexString(Operands[0]) << " "
388 << hexString(Operands[1]) << "#";
389 break;
390 }
391
393}
394
395namespace {
396const char *const KindBaseClassOffset = "BaseClassOffset";
397const char *const KindBaseClassStep = "BaseClassStep";
398const char *const KindClassOffset = "ClassOffset";
399const char *const KindFixedAddress = "FixedAddress";
400const char *const KindMissingInfo = "Missing";
401const char *const KindOperation = "Operation";
402const char *const KindOperationList = "OperationList";
403const char *const KindRegister = "Register";
404const char *const KindUndefined = "Undefined";
405}
406
407
408
409
411 const char *Kind = KindUndefined;
412 if (getIsBaseClassOffset())
413 Kind = KindBaseClassOffset;
414 else if (getIsBaseClassStep())
415 Kind = KindBaseClassStep;
416 else if (getIsClassOffset())
417 Kind = KindClassOffset;
418 else if (getIsFixedAddress())
419 Kind = KindFixedAddress;
420 else if (getIsGapEntry())
421 Kind = KindMissingInfo;
422 else if (getIsOperation())
423 Kind = KindOperation;
424 else if (getIsOperationList())
425 Kind = KindOperationList;
426 else if (getIsRegister())
427 Kind = KindRegister;
429}
430
432 static const char *const Question = "?";
435 if (getIsAddressRange())
436 Stream << "{Range}";
437
438 auto PrintLine = [&](const LVLine *Line) {
440 std::string TheLine;
441 TheLine = Line->lineNumberAsStringStripped();
442 Stream << TheLine.c_str();
443 } else {
444 Stream << Question;
445 }
446 };
447
448 Stream << " Lines ";
450 Stream << ":";
452
453 if (options().getAttributeOffset())
454
457
459}
460
461
463
464
465
466
467
468
469 if (!hasAssociatedRange())
470 return true;
471
475 if (LowLine)
477 else {
478 setIsInvalidLower();
479 return false;
480 }
481 if (HighLine)
483 else {
484 setIsInvalidUpper();
485 return false;
486 }
487
489 setIsInvalidRange();
490 return false;
491 }
492
493 return true;
494}
495
497 float &Percentage) {
499 return false;
500
501
502
504
506
507
509 if (Location->getIsLocationSimple()) {
510 Factor = 100;
511 Percentage = 100;
512 return true;
513 }
514 }
515
516
520
521 if (->getIsGapEntry()) {
522 LowerAddress = Location->getLowerAddress();
523 UpperAddress = Location->getUpperAddress();
524 Factor += (UpperAddress > LowerAddress) ? UpperAddress - LowerAddress
525 : LowerAddress - UpperAddress;
526 }
527
528 Percentage = 0;
529 return false;
530}
531
539
541 if (hasAssociatedRange())
543}
544
546 if (getReader().doPrintLocation(this)) {
549 }
550}
551
556
557
558
559
560
566
567
568 setOffset(LocDescOffset ? LocDescOffset : SectionOffset);
569
570
572 setIsDiscardedRange();
573
574
576}
577
578
581 if (!Entries)
582 Entries = std::make_unique();
583 Entries->push_back(getReader().createOperation(Opcode, Operands));
584}
585
586
589 case dwarf::DW_AT_data_member_location:
590 setIsClassOffset();
591 break;
592 case dwarf::DW_AT_location:
593
594 setIsFixedAddress();
595 break;
596 default:
597 break;
598 }
599
600
601
602 if (hasAssociatedRange())
604}
605
607
608 if (Entries && Entries->size() == 1) {
609 if (dwarf::DW_OP_fbreg == Entries->front()->getOpcode())
610 setIsStackOffset();
611 }
612}
613
619
620
623 return;
624
625
626 if (options().getAttributeCoverage()) {
627
628
631 float Percentage = Symbol->getCoveragePercentage();
632
633
636 Stream << format("%.2f%%", Percentage);
637 if (->getIsLocationSimple())
638 Stream << format(" (%d/%d)", Symbol->getCoverageFactor(),
639 Symbol->getParentScope()->getCoverageFactor());
641 false,
642 false);
643 }
644
645
646 if (getReader().doPrintLocation(nullptr))
649}
650
652 OS << "{Location}";
653 if (getIsCallSite())
654 OS << " -> CallSite";
656 OS << "\n";
657
658
659 if (Full && Entries) {
660 bool CodeViewLocation = getParentSymbol()->getHasCodeViewLocation();
661 std::stringstream Stream;
662 std::string Leading;
664 Stream << Leading
665 << (CodeViewLocation ? Operation->getOperandsCodeViewInfo()
666 : Operation->getOperandsDWARFInfo());
667 Leading = ", ";
668 }
671 false,
672 false);
673 }
674}
static std::string getRegisterName(const TargetRegisterInfo *TRI, Register Reg)
PowerPC Reduce CR logical Operation
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
StringRef - Represent a constant reference to a string, i.e.
void printExtra(raw_ostream &OS, bool Full=true) const override
Definition LVLocation.cpp:651
void printRawExtra(raw_ostream &OS, bool Full=true) const override
Definition LVLocation.cpp:614
void addObject(LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset, uint64_t LocDescOffset) override
Definition LVLocation.cpp:561
const char * kind() const override
Definition LVLocation.cpp:410
static bool calculateCoverage(LVLocations *Locations, unsigned &Factor, float &Percentage)
Definition LVLocation.cpp:496
void setUpperAddress(LVAddress Address) override
const LVLine * getLowerLine() const
void setUpperLine(LVLine *Line)
virtual void updateKind()
std::string getIntervalInfo() const
Definition LVLocation.cpp:431
virtual void printRawExtra(raw_ostream &OS, bool Full=true) const
void printRaw(raw_ostream &OS, bool Full=true) const
Definition LVLocation.cpp:532
LVAddress getLowerAddress() const override
void setKind()
Definition LVLocation.cpp:587
bool validateRanges()
Definition LVLocation.cpp:462
const LVLine * getUpperLine() const
void printExtra(raw_ostream &OS, bool Full=true) const override
Definition LVLocation.cpp:552
static void print(LVLocations *Locations, raw_ostream &OS, bool Full=true)
Definition LVLocation.cpp:621
void setLowerLine(LVLine *Line)
LVAddress getUpperAddress() const override
void printInterval(raw_ostream &OS, bool Full=true) const
Definition LVLocation.cpp:540
void setLowerAddress(LVAddress Address) override
virtual void print(raw_ostream &OS, bool Full=true) const
void printAttributes(raw_ostream &OS, bool Full=true) const
dwarf::Attribute getAttr() const
LVSymbol * getParentSymbol() const
uint32_t getLineNumber() const
void setOffset(LVOffset DieOffset)
LLVM_ABI void print(raw_ostream &OS, bool Full=true) const
Definition LVLocation.cpp:23
LLVM_ABI std::string getOperandsDWARFInfo()
Definition LVLocation.cpp:27
LLVM_ABI std::string getOperandsCodeViewInfo()
Definition LVLocation.cpp:347
virtual std::string getRegisterName(LVSmall Opcode, ArrayRef< uint64_t > Operands)
LVLineRange lineRange(LVLocation *Location) const
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
std::string hexString(uint64_t Value, size_t Width=HEX_WIDTH)
uint16_t getCodeViewOperationCode(uint8_t Code)
LVScopeCompileUnit * getReaderCompileUnit()
std::pair< LVLine *, LVLine * > LVLineRange
const LVSmall LVLocationMemberOffset
SmallVector< LVLocation *, 8 > LVLocations
This is an optimization pass for GlobalISel generic memory operations.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.