1 //===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===//
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
9 #include "llvm/ADT/SmallVector.h"
10 #include "llvm/ADT/StringExtras.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Config/llvm-config.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCFixup.h"
15 #include "llvm/MC/MCSection.h"
16 #include "llvm/MC/MCSectionMachO.h"
17 #include "llvm/MC/MCSymbol.h"
18 #include "llvm/Support/Casting.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include <cassert>
22 #include <type_traits>
23 #include <utility>
24
25 using namespace llvm;
26
27 static_assert(std::is_trivially_destructible_v<MCDataFragment>,
28 "fragment classes must be trivially destructible");
29
MCFragment(FragmentType Kind,bool HasInstructions)30 MCFragment::MCFragment(FragmentType Kind, bool HasInstructions)
31 : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false),
32 LinkerRelaxable(false), AllowAutoPadding(false) {}
33
getAtom() const34 const MCSymbol *MCFragment::getAtom() const {
35 return cast<MCSectionMachO>(Parent)->getAtom(LayoutOrder);
36 }
37
38 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const39 LLVM_DUMP_METHOD void MCFragment::dump() const {
40 raw_ostream &OS = errs();
41
42 OS << Offset << ' ';
43 switch (getKind()) {
44 // clang-format off
45 case MCFragment::FT_Align: OS << "Align"; break;
46 case MCFragment::FT_Data: OS << "Data"; break;
47 case MCFragment::FT_Fill: OS << "Fill"; break;
48 case MCFragment::FT_Nops: OS << "Nops"; break;
49 case MCFragment::FT_Relaxable: OS << "Relaxable"; break;
50 case MCFragment::FT_Org: OS << "Org"; break;
51 case MCFragment::FT_Dwarf: OS << "Dwarf"; break;
52 case MCFragment::FT_DwarfFrame: OS << "DwarfCallFrame"; break;
53 case MCFragment::FT_LEB: OS << "LEB"; break;
54 case MCFragment::FT_BoundaryAlign: OS<<"BoundaryAlign"; break;
55 case MCFragment::FT_SymbolId: OS << "SymbolId"; break;
56 case MCFragment::FT_CVInlineLines: OS << "CVInlineLineTable"; break;
57 case MCFragment::FT_CVDefRange: OS << "CVDefRangeTable"; break;
58 case MCFragment::FT_PseudoProbe: OS << "PseudoProbe"; break;
59 // clang-format on
60 }
61
62 if (const auto *EF = dyn_cast<MCEncodedFragment>(this))
63 if (auto Pad = static_cast<unsigned>(EF->getBundlePadding()))
64 OS << " BundlePadding:" << Pad;
65
66 auto printFixups = [&](llvm::ArrayRef<MCFixup> Fixups) {
67 if (Fixups.empty())
68 return;
69 for (auto [I, F] : llvm::enumerate(Fixups)) {
70 OS << "\n Fixup @" << F.getOffset() << " Value:";
71 F.getValue()->print(OS, nullptr);
72 OS << " Kind:" << F.getKind();
73 if (F.isLinkerRelaxable())
74 OS << " LinkerRelaxable";
75 }
76 };
77
78 switch (getKind()) {
79 case MCFragment::FT_Align: {
80 const auto *AF = cast<MCAlignFragment>(this);
81 OS << " Align:" << AF->getAlignment().value() << " Fill:" << AF->getFill()
82 << " FillLen:" << unsigned(AF->getFillLen())
83 << " MaxBytesToEmit:" << AF->getMaxBytesToEmit();
84 if (AF->hasEmitNops())
85 OS << " Nops";
86 break;
87 }
88 case MCFragment::FT_Data: {
89 const auto *F = cast<MCDataFragment>(this);
90 if (F->isLinkerRelaxable())
91 OS << " LinkerRelaxable";
92 auto Contents = F->getContents();
93 OS << " Size:" << Contents.size() << " [";
94 for (unsigned i = 0, e = Contents.size(); i != e; ++i) {
95 if (i) OS << ",";
96 OS << format("%02x", uint8_t(Contents[i]));
97 }
98 OS << ']';
99 printFixups(F->getFixups());
100 break;
101 }
102 case MCFragment::FT_Fill: {
103 const auto *FF = cast<MCFillFragment>(this);
104 OS << " Value:" << static_cast<unsigned>(FF->getValue())
105 << " ValueSize:" << static_cast<unsigned>(FF->getValueSize())
106 << " NumValues:";
107 FF->getNumValues().print(OS, nullptr);
108 break;
109 }
110 case MCFragment::FT_Nops: {
111 const auto *NF = cast<MCNopsFragment>(this);
112 OS << " NumBytes:" << NF->getNumBytes()
113 << " ControlledNopLength:" << NF->getControlledNopLength();
114 break;
115 }
116 case MCFragment::FT_Relaxable: {
117 const auto *F = cast<MCRelaxableFragment>(this);
118 if (F->isLinkerRelaxable())
119 OS << " LinkerRelaxable";
120 OS << " Size:" << F->getContents().size() << ' ';
121 F->getInst().dump_pretty(OS);
122 printFixups(F->getFixups());
123 break;
124 }
125 case MCFragment::FT_Org: {
126 const auto *OF = cast<MCOrgFragment>(this);
127 OS << " Offset:";
128 OF->getOffset().print(OS, nullptr);
129 OS << " Value:" << static_cast<unsigned>(OF->getValue());
130 break;
131 }
132 case MCFragment::FT_Dwarf: {
133 const auto *OF = cast<MCDwarfLineAddrFragment>(this);
134 OS << " AddrDelta:";
135 OF->getAddrDelta().print(OS, nullptr);
136 OS << " LineDelta:" << OF->getLineDelta();
137 break;
138 }
139 case MCFragment::FT_DwarfFrame: {
140 const auto *CF = cast<MCDwarfCallFrameFragment>(this);
141 OS << " AddrDelta:";
142 CF->getAddrDelta().print(OS, nullptr);
143 break;
144 }
145 case MCFragment::FT_LEB: {
146 const auto *LF = cast<MCLEBFragment>(this);
147 OS << " Value:";
148 LF->getValue().print(OS, nullptr);
149 OS << " Signed:" << LF->isSigned();
150 break;
151 }
152 case MCFragment::FT_BoundaryAlign: {
153 const auto *BF = cast<MCBoundaryAlignFragment>(this);
154 OS << " BoundarySize:" << BF->getAlignment().value()
155 << " LastFragment:" << BF->getLastFragment()
156 << " Size:" << BF->getSize();
157 break;
158 }
159 case MCFragment::FT_SymbolId: {
160 const auto *F = cast<MCSymbolIdFragment>(this);
161 OS << " Sym:" << F->getSymbol();
162 break;
163 }
164 case MCFragment::FT_CVInlineLines: {
165 const auto *F = cast<MCCVInlineLineTableFragment>(this);
166 OS << " Sym:" << *F->getFnStartSym();
167 break;
168 }
169 case MCFragment::FT_CVDefRange: {
170 const auto *F = cast<MCCVDefRangeFragment>(this);
171 OS << "\n ";
172 for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd :
173 F->getRanges()) {
174 OS << " RangeStart:" << RangeStartEnd.first;
175 OS << " RangeEnd:" << RangeStartEnd.second;
176 }
177 break;
178 }
179 case MCFragment::FT_PseudoProbe: {
180 const auto *OF = cast<MCPseudoProbeAddrFragment>(this);
181 OS << " AddrDelta:";
182 OF->getAddrDelta().print(OS, nullptr);
183 break;
184 }
185 }
186 }
187 #endif
188