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
25using namespace llvm;
26
27static_assert(std::is_trivially_destructible_v<MCFragment>,
28 "fragment classes must be trivially destructible");
29
30MCFragment::MCFragment(FragmentType Kind, bool HasInstructions)
31 : Kind(Kind), LinkerRelaxable(false), HasInstructions(HasInstructions),
32 AllowAutoPadding(false) {
33 static_assert(sizeof(MCFragment::Tail) <= 16,
34 "Keep the variable-size tail small");
35}
36
37const MCSymbol *MCFragment::getAtom() const {
38 return static_cast<const MCSectionMachO *>(Parent)->getAtom(I: LayoutOrder);
39}
40
41#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
42LLVM_DUMP_METHOD void MCFragment::dump() const {
43 raw_ostream &OS = errs();
44
45 OS << Offset << ' ';
46 switch (getKind()) {
47 // clang-format off
48 case MCFragment::FT_Align: OS << "Align"; break;
49 case MCFragment::FT_Data: OS << "Data"; break;
50 case MCFragment::FT_Fill: OS << "Fill"; break;
51 case MCFragment::FT_Nops: OS << "Nops"; break;
52 case MCFragment::FT_Relaxable: OS << "Relaxable"; break;
53 case MCFragment::FT_Org: OS << "Org"; break;
54 case MCFragment::FT_Dwarf: OS << "Dwarf"; break;
55 case MCFragment::FT_DwarfFrame: OS << "DwarfCallFrame"; break;
56 case MCFragment::FT_SFrame: OS << "SFrame"; break;
57 case MCFragment::FT_LEB: OS << "LEB"; break;
58 case MCFragment::FT_BoundaryAlign: OS << "BoundaryAlign"; break;
59 case MCFragment::FT_PrefAlign: OS << "PrefAlign"; break;
60 case MCFragment::FT_SymbolId: OS << "SymbolId"; break;
61 case MCFragment::FT_CVInlineLines: OS << "CVInlineLineTable"; break;
62 case MCFragment::FT_CVDefRange: OS << "CVDefRangeTable"; break;
63 // clang-format on
64 }
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_Data:
80 case MCFragment::FT_Relaxable:
81 case MCFragment::FT_Align:
82 case MCFragment::FT_LEB:
83 case MCFragment::FT_Dwarf:
84 case MCFragment::FT_DwarfFrame:
85 case MCFragment::FT_SFrame: {
86 if (isLinkerRelaxable())
87 OS << " LinkerRelaxable";
88 auto Fixed = getContents();
89 auto Var = getVarContents();
90 OS << " Size:" << Fixed.size();
91 if (getKind() != MCFragment::FT_Data) {
92 OS << '+' << Var.size();
93 // FT_Align uses getVarContents to track the size, but the content is
94 // ignored and not useful.
95 if (getKind() == MCFragment::FT_Align)
96 Var = {};
97 }
98 OS << " [";
99 for (unsigned i = 0, e = Fixed.size(); i != e; ++i) {
100 if (i) OS << ",";
101 OS << format("%02x", uint8_t(Fixed[i]));
102 }
103 for (unsigned i = 0, e = Var.size(); i != e; ++i) {
104 if (Fixed.size() || i)
105 OS << ",";
106 OS << format("%02x", uint8_t(Var[i]));
107 }
108 OS << ']';
109 switch (getKind()) {
110 case MCFragment::FT_Data:
111 break;
112 case MCFragment::FT_Relaxable:
113 OS << ' ';
114 getInst().dump_pretty(OS);
115 break;
116 case MCFragment::FT_Align:
117 OS << "\n Align:" << getAlignment().value() << " Fill:" << getAlignFill()
118 << " FillLen:" << unsigned(getAlignFillLen())
119 << " MaxBytesToEmit:" << getAlignMaxBytesToEmit();
120 if (hasAlignEmitNops())
121 OS << " Nops";
122 break;
123 case MCFragment::FT_LEB: {
124 OS << " Value:";
125 getLEBValue().print(OS, nullptr);
126 OS << " Signed:" << isLEBSigned();
127 break;
128 }
129 case MCFragment::FT_Dwarf:
130 OS << " AddrDelta:";
131 getDwarfAddrDelta().print(OS, nullptr);
132 OS << " LineDelta:" << getDwarfLineDelta();
133 break;
134 case MCFragment::FT_DwarfFrame:
135 case MCFragment::FT_SFrame:
136 OS << " AddrDelta:";
137 getDwarfAddrDelta().print(OS, nullptr);
138 break;
139 default:
140 llvm_unreachable("");
141 }
142 printFixups(getFixups());
143 printFixups(getVarFixups());
144 break;
145 }
146 case MCFragment::FT_Fill: {
147 const auto *FF = cast<MCFillFragment>(this);
148 OS << " Value:" << static_cast<unsigned>(FF->getValue())
149 << " ValueSize:" << static_cast<unsigned>(FF->getValueSize())
150 << " NumValues:";
151 FF->getNumValues().print(OS, nullptr);
152 break;
153 }
154 case MCFragment::FT_Nops: {
155 const auto *NF = cast<MCNopsFragment>(this);
156 OS << " NumBytes:" << NF->getNumBytes()
157 << " ControlledNopLength:" << NF->getControlledNopLength();
158 break;
159 }
160 case MCFragment::FT_Org: {
161 const auto *OF = cast<MCOrgFragment>(this);
162 OS << " Offset:";
163 OF->getOffset().print(OS, nullptr);
164 OS << " Value:" << static_cast<unsigned>(OF->getValue());
165 break;
166 }
167 case MCFragment::FT_BoundaryAlign: {
168 const auto *BF = cast<MCBoundaryAlignFragment>(this);
169 OS << " BoundarySize:" << BF->getAlignment().value()
170 << " LastFragment:" << BF->getLastFragment()
171 << " Size:" << BF->getSize();
172 break;
173 }
174 case MCFragment::FT_PrefAlign:
175 OS << " PrefAlign:" << getPrefAlignPreferred().value()
176 << " End:" << getPrefAlignEnd().getName()
177 << " ComputedAlign:" << getPrefAlignComputed().value();
178 break;
179 case MCFragment::FT_SymbolId: {
180 const auto *F = cast<MCSymbolIdFragment>(this);
181 OS << " Sym:" << F->getSymbol();
182 break;
183 }
184 case MCFragment::FT_CVInlineLines: {
185 const auto *F = cast<MCCVInlineLineTableFragment>(this);
186 OS << " Sym:" << *F->getFnStartSym();
187 break;
188 }
189 case MCFragment::FT_CVDefRange: {
190 const auto *F = cast<MCCVDefRangeFragment>(this);
191 OS << "\n ";
192 for (std::pair<const MCSymbol *, const MCSymbol *> RangeStartEnd :
193 F->getRanges()) {
194 OS << " RangeStart:" << RangeStartEnd.first;
195 OS << " RangeEnd:" << RangeStartEnd.second;
196 }
197 break;
198 }
199 }
200}
201#endif
202