LLVM 24.0.0git
DWARFCFIPrinter.cpp
Go to the documentation of this file.
1//===- DWARFCFIPrinter.cpp - Print the cfi-portions of .debug_frame -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
17#include <cassert>
18#include <cstdint>
19#include <optional>
20
21using namespace llvm;
22using namespace dwarf;
23
24static void printRegister(raw_ostream &OS, const DIDumpOptions &DumpOpts,
25 unsigned RegNum) {
26 if (DumpOpts.GetNameForDWARFReg) {
27 auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);
28 if (!RegName.empty()) {
29 OS << RegName;
30 return;
31 }
32 }
33 OS << "reg" << RegNum;
34}
35
36/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
37static void printOperand(raw_ostream &OS, const DIDumpOptions &DumpOpts,
38 const CFIProgram &P,
39 const CFIProgram::Instruction &Instr,
40 unsigned OperandIdx, uint64_t Operand,
41 std::optional<uint64_t> &Address) {
42 assert(OperandIdx < CFIProgram::MaxOperands);
43 uint8_t Opcode = Instr.Opcode;
44 CFIProgram::OperandType Type = P.getOperandTypes()[Opcode][OperandIdx];
45
46 switch (Type) {
48 OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
49 auto OpcodeName = P.callFrameString(Opcode);
50 if (!OpcodeName.empty())
51 OS << " " << OpcodeName;
52 else
53 OS << formatv(" Opcode {0:x-}", Opcode);
54 break;
55 }
57 break;
59 OS << formatv(" {0:x-}", Operand);
60 Address = Operand;
61 break;
63 // The offsets are all encoded in a unsigned form, but in practice
64 // consumers use them signed. It's most certainly legacy due to
65 // the lack of signed variants in the first Dwarf standards.
66 OS << formatv(" {0:+d}", int64_t(Operand));
67 break;
68 case CFIProgram::OT_FactoredCodeOffset: // Always Unsigned
69 if (P.codeAlign())
70 OS << formatv(" {0}", int64_t(Operand * P.codeAlign()));
71 else
72 OS << formatv(" {0}*code_alignment_factor", int64_t(Operand));
73 if (Address && P.codeAlign()) {
74 *Address += Operand * P.codeAlign();
75 OS << formatv(" to {0:x+}", *Address);
76 }
77 break;
79 if (P.dataAlign())
80 OS << formatv(" {0}", int64_t(Operand) * P.dataAlign());
81 else
82 OS << formatv(" {0}*data_alignment_factor", int64_t(Operand));
83 break;
85 if (P.codeAlign())
86 OS << formatv(" {0}", int64_t(Operand) * (int64_t)P.codeAlign());
87 else
88 OS << formatv(" {0}*code_alignment_factor", int64_t(Operand));
89 break;
91 if (P.dataAlign())
92 OS << formatv(" {0}", int64_t(Operand * P.dataAlign()));
93 else
94 OS << formatv(" {0}*data_alignment_factor", int64_t(Operand));
95 break;
97 OS << ' ';
98 printRegister(OS, DumpOpts, Operand);
99 break;
101 OS << ' ' << Operand;
102 break;
104 OS << formatv(" in addrspace{0}", Operand);
105 break;
107 assert(Instr.Expression && "missing DWARFExpression object");
108 OS << " ";
109 printDwarfExpression(&Instr.Expression.value(), OS, DumpOpts, nullptr);
110 break;
111 }
112}
113
115 const DIDumpOptions &DumpOpts,
116 unsigned IndentLevel,
117 std::optional<uint64_t> Address) {
118 for (const auto &Instr : P) {
119 uint8_t Opcode = Instr.Opcode;
120 OS.indent(2 * IndentLevel);
121 OS << P.callFrameString(Opcode) << ":";
122 for (size_t i = 0; i < Instr.Ops.size(); ++i)
123 printOperand(OS, DumpOpts, P, Instr, i, Instr.Ops[i], Address);
124 OS << '\n';
125 }
126}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static void printOperand(raw_ostream &OS, const DIDumpOptions &DumpOpts, const CFIProgram &P, const CFIProgram::Instruction &Instr, unsigned OperandIdx, uint64_t Operand, std::optional< uint64_t > &Address)
Print Opcode's operand number OperandIdx which has value Operand.
static void printRegister(raw_ostream &OS, const DIDumpOptions &DumpOpts, unsigned RegNum)
#define RegName(no)
#define P(N)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
Represent a sequence of Call Frame Information instructions that, when read in order,...
OperandType
Types of operands to CFI instructions In DWARF, this type is implicitly tied to a CFI instruction opc...
static constexpr size_t MaxOperands
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Calculates the starting offsets for various sections within the .debug_names section.
Definition Dwarf.h:35
LLVM_ABI void printCFIProgram(const CFIProgram &P, raw_ostream &OS, const DIDumpOptions &DumpOpts, unsigned IndentLevel, std::optional< uint64_t > Address)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U, bool IsEH=false)
Print a Dwarf expression/.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Container for dump options that control which debug information will be dumped.
Definition DIContext.h:196
std::function< llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)> GetNameForDWARFReg
Definition DIContext.h:217
An instruction consists of a DWARF CFI opcode and an optional sequence of operands.