1//===- MCFragment.h - Fragment type hierarchy -------------------*- C++ -*-===//
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#ifndef LLVM_MC_MCFRAGMENT_H
10#define LLVM_MC_MCFRAGMENT_H
11
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/SmallString.h"
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/ADT/StringRef.h"
16#include "llvm/ADT/ilist_node.h"
17#include "llvm/MC/MCFixup.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/Support/Alignment.h"
20#include "llvm/Support/SMLoc.h"
21#include <cstdint>
22#include <utility>
23
24namespace llvm {
25
26class MCSection;
27class MCSubtargetInfo;
28class MCSymbol;
29
30class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
31 friend class MCAsmLayout;
32
33public:
34 enum FragmentType : uint8_t {
35 FT_Align,
36 FT_Data,
37 FT_CompactEncodedInst,
38 FT_Fill,
39 FT_Nops,
40 FT_Relaxable,
41 FT_Org,
42 FT_Dwarf,
43 FT_DwarfFrame,
44 FT_LEB,
45 FT_BoundaryAlign,
46 FT_SymbolId,
47 FT_CVInlineLines,
48 FT_CVDefRange,
49 FT_PseudoProbe,
50 FT_Dummy
51 };
52
53private:
54 /// The data for the section this fragment is in.
55 MCSection *Parent;
56
57 /// The atom this fragment is in, as represented by its defining symbol.
58 const MCSymbol *Atom;
59
60 /// The offset of this fragment in its section. This is ~0 until
61 /// initialized.
62 uint64_t Offset;
63
64 /// The layout order of this fragment.
65 unsigned LayoutOrder;
66
67 /// The subsection this fragment belongs to. This is 0 if the fragment is not
68 // in any subsection.
69 unsigned SubsectionNumber = 0;
70
71 FragmentType Kind;
72
73 /// Whether fragment is being laid out.
74 bool IsBeingLaidOut;
75
76protected:
77 bool HasInstructions;
78 bool LinkerRelaxable = false;
79
80 MCFragment(FragmentType Kind, bool HasInstructions,
81 MCSection *Parent = nullptr);
82
83public:
84 MCFragment() = delete;
85 MCFragment(const MCFragment &) = delete;
86 MCFragment &operator=(const MCFragment &) = delete;
87
88 /// Destroys the current fragment.
89 ///
90 /// This must be used instead of delete as MCFragment is non-virtual.
91 /// This method will dispatch to the appropriate subclass.
92 void destroy();
93
94 FragmentType getKind() const { return Kind; }
95
96 MCSection *getParent() const { return Parent; }
97 void setParent(MCSection *Value) { Parent = Value; }
98
99 const MCSymbol *getAtom() const { return Atom; }
100 void setAtom(const MCSymbol *Value) { Atom = Value; }
101
102 unsigned getLayoutOrder() const { return LayoutOrder; }
103 void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
104
105 /// Does this fragment have instructions emitted into it? By default
106 /// this is false, but specific fragment types may set it to true.
107 bool hasInstructions() const { return HasInstructions; }
108
109 void dump() const;
110
111 void setSubsectionNumber(unsigned Value) { SubsectionNumber = Value; }
112 unsigned getSubsectionNumber() const { return SubsectionNumber; }
113};
114
115class MCDummyFragment : public MCFragment {
116public:
117 explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {}
118
119 static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
120};
121
122/// Interface implemented by fragments that contain encoded instructions and/or
123/// data.
124///
125class MCEncodedFragment : public MCFragment {
126 /// Should this fragment be aligned to the end of a bundle?
127 bool AlignToBundleEnd = false;
128
129 uint8_t BundlePadding = 0;
130
131protected:
132 MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
133 MCSection *Sec)
134 : MCFragment(FType, HasInstructions, Sec) {}
135
136 /// The MCSubtargetInfo in effect when the instruction was encoded.
137 /// It must be non-null for instructions.
138 const MCSubtargetInfo *STI = nullptr;
139
140public:
141 static bool classof(const MCFragment *F) {
142 MCFragment::FragmentType Kind = F->getKind();
143 switch (Kind) {
144 default:
145 return false;
146 case MCFragment::FT_Relaxable:
147 case MCFragment::FT_CompactEncodedInst:
148 case MCFragment::FT_Data:
149 case MCFragment::FT_Dwarf:
150 case MCFragment::FT_DwarfFrame:
151 case MCFragment::FT_PseudoProbe:
152 return true;
153 }
154 }
155
156 /// Should this fragment be placed at the end of an aligned bundle?
157 bool alignToBundleEnd() const { return AlignToBundleEnd; }
158 void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
159
160 /// Get the padding size that must be inserted before this fragment.
161 /// Used for bundling. By default, no padding is inserted.
162 /// Note that padding size is restricted to 8 bits. This is an optimization
163 /// to reduce the amount of space used for each fragment. In practice, larger
164 /// padding should never be required.
165 uint8_t getBundlePadding() const { return BundlePadding; }
166
167 /// Set the padding size for this fragment. By default it's a no-op,
168 /// and only some fragments have a meaningful implementation.
169 void setBundlePadding(uint8_t N) { BundlePadding = N; }
170
171 /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
172 /// Guaranteed to be non-null if hasInstructions() == true
173 const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
174
175 /// Record that the fragment contains instructions with the MCSubtargetInfo in
176 /// effect when the instruction was encoded.
177 void setHasInstructions(const MCSubtargetInfo &STI) {
178 HasInstructions = true;
179 this->STI = &STI;
180 }
181};
182
183/// Interface implemented by fragments that contain encoded instructions and/or
184/// data.
185///
186template<unsigned ContentsSize>
187class MCEncodedFragmentWithContents : public MCEncodedFragment {
188 SmallVector<char, ContentsSize> Contents;
189
190protected:
191 MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
192 bool HasInstructions,
193 MCSection *Sec)
194 : MCEncodedFragment(FType, HasInstructions, Sec) {}
195
196public:
197 SmallVectorImpl<char> &getContents() { return Contents; }
198 const SmallVectorImpl<char> &getContents() const { return Contents; }
199};
200
201/// Interface implemented by fragments that contain encoded instructions and/or
202/// data and also have fixups registered.
203///
204template<unsigned ContentsSize, unsigned FixupsSize>
205class MCEncodedFragmentWithFixups :
206 public MCEncodedFragmentWithContents<ContentsSize> {
207
208 /// The list of fixups in this fragment.
209 SmallVector<MCFixup, FixupsSize> Fixups;
210
211protected:
212 MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
213 bool HasInstructions,
214 MCSection *Sec)
215 : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
216 Sec) {}
217
218public:
219
220 using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
221 using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
222
223 SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
224 const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
225
226 fixup_iterator fixup_begin() { return Fixups.begin(); }
227 const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
228
229 fixup_iterator fixup_end() { return Fixups.end(); }
230 const_fixup_iterator fixup_end() const { return Fixups.end(); }
231
232 static bool classof(const MCFragment *F) {
233 MCFragment::FragmentType Kind = F->getKind();
234 return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
235 Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
236 Kind == MCFragment::FT_DwarfFrame;
237 }
238};
239
240/// Fragment for data and encoded instructions.
241///
242class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
243public:
244 MCDataFragment(MCSection *Sec = nullptr)
245 : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
246
247 static bool classof(const MCFragment *F) {
248 return F->getKind() == MCFragment::FT_Data;
249 }
250
251 bool isLinkerRelaxable() const { return LinkerRelaxable; }
252 void setLinkerRelaxable() { LinkerRelaxable = true; }
253};
254
255/// This is a compact (memory-size-wise) fragment for holding an encoded
256/// instruction (non-relaxable) that has no fixups registered. When applicable,
257/// it can be used instead of MCDataFragment and lead to lower memory
258/// consumption.
259///
260class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
261public:
262 MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
263 : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) {
264 }
265
266 static bool classof(const MCFragment *F) {
267 return F->getKind() == MCFragment::FT_CompactEncodedInst;
268 }
269};
270
271/// A relaxable fragment holds on to its MCInst, since it may need to be
272/// relaxed during the assembler layout and relaxation stage.
273///
274class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
275
276 /// The instruction this is a fragment for.
277 MCInst Inst;
278 /// Can we auto pad the instruction?
279 bool AllowAutoPadding = false;
280
281public:
282 MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
283 MCSection *Sec = nullptr)
284 : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
285 Inst(Inst) { this->STI = &STI; }
286
287 const MCInst &getInst() const { return Inst; }
288 void setInst(const MCInst &Value) { Inst = Value; }
289
290 bool getAllowAutoPadding() const { return AllowAutoPadding; }
291 void setAllowAutoPadding(bool V) { AllowAutoPadding = V; }
292
293 static bool classof(const MCFragment *F) {
294 return F->getKind() == MCFragment::FT_Relaxable;
295 }
296};
297
298class MCAlignFragment : public MCFragment {
299 /// The alignment to ensure, in bytes.
300 Align Alignment;
301
302 /// Flag to indicate that (optimal) NOPs should be emitted instead
303 /// of using the provided value. The exact interpretation of this flag is
304 /// target dependent.
305 bool EmitNops : 1;
306
307 /// Value to use for filling padding bytes.
308 int64_t Value;
309
310 /// The size of the integer (in bytes) of \p Value.
311 unsigned ValueSize;
312
313 /// The maximum number of bytes to emit; if the alignment
314 /// cannot be satisfied in this width then this fragment is ignored.
315 unsigned MaxBytesToEmit;
316
317 /// When emitting Nops some subtargets have specific nop encodings.
318 const MCSubtargetInfo *STI = nullptr;
319
320public:
321 MCAlignFragment(Align Alignment, int64_t Value, unsigned ValueSize,
322 unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
323 : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
324 Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
325
326 Align getAlignment() const { return Alignment; }
327
328 int64_t getValue() const { return Value; }
329
330 unsigned getValueSize() const { return ValueSize; }
331
332 unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
333
334 bool hasEmitNops() const { return EmitNops; }
335 void setEmitNops(bool Value, const MCSubtargetInfo *STI) {
336 EmitNops = Value;
337 this->STI = STI;
338 }
339
340 const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
341
342 static bool classof(const MCFragment *F) {
343 return F->getKind() == MCFragment::FT_Align;
344 }
345};
346
347class MCFillFragment : public MCFragment {
348 uint8_t ValueSize;
349 /// Value to use for filling bytes.
350 uint64_t Value;
351 /// The number of bytes to insert.
352 const MCExpr &NumValues;
353
354 /// Source location of the directive that this fragment was created for.
355 SMLoc Loc;
356
357public:
358 MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
359 SMLoc Loc, MCSection *Sec = nullptr)
360 : MCFragment(FT_Fill, false, Sec), ValueSize(VSize), Value(Value),
361 NumValues(NumValues), Loc(Loc) {}
362
363 uint64_t getValue() const { return Value; }
364 uint8_t getValueSize() const { return ValueSize; }
365 const MCExpr &getNumValues() const { return NumValues; }
366
367 SMLoc getLoc() const { return Loc; }
368
369 static bool classof(const MCFragment *F) {
370 return F->getKind() == MCFragment::FT_Fill;
371 }
372};
373
374class MCNopsFragment : public MCFragment {
375 /// The number of bytes to insert.
376 int64_t Size;
377 /// Maximum number of bytes allowed in each NOP instruction.
378 int64_t ControlledNopLength;
379
380 /// Source location of the directive that this fragment was created for.
381 SMLoc Loc;
382
383 /// When emitting Nops some subtargets have specific nop encodings.
384 const MCSubtargetInfo &STI;
385
386public:
387 MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
388 const MCSubtargetInfo &STI, MCSection *Sec = nullptr)
389 : MCFragment(FT_Nops, false, Sec), Size(NumBytes),
390 ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {}
391
392 int64_t getNumBytes() const { return Size; }
393 int64_t getControlledNopLength() const { return ControlledNopLength; }
394
395 SMLoc getLoc() const { return Loc; }
396
397 const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
398
399 static bool classof(const MCFragment *F) {
400 return F->getKind() == MCFragment::FT_Nops;
401 }
402};
403
404class MCOrgFragment : public MCFragment {
405 /// Value to use for filling bytes.
406 int8_t Value;
407
408 /// The offset this fragment should start at.
409 const MCExpr *Offset;
410
411 /// Source location of the directive that this fragment was created for.
412 SMLoc Loc;
413
414public:
415 MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
416 MCSection *Sec = nullptr)
417 : MCFragment(FT_Org, false, Sec), Value(Value), Offset(&Offset),
418 Loc(Loc) {}
419
420 const MCExpr &getOffset() const { return *Offset; }
421
422 uint8_t getValue() const { return Value; }
423
424 SMLoc getLoc() const { return Loc; }
425
426 static bool classof(const MCFragment *F) {
427 return F->getKind() == MCFragment::FT_Org;
428 }
429};
430
431class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
432 /// True if this is a sleb128, false if uleb128.
433 bool IsSigned;
434
435 /// The value this fragment should contain.
436 const MCExpr *Value;
437
438public:
439 MCLEBFragment(const MCExpr &Value, bool IsSigned, MCSection *Sec = nullptr)
440 : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false, Sec),
441 IsSigned(IsSigned), Value(&Value) {
442 getContents().push_back(Elt: 0);
443 }
444
445 const MCExpr &getValue() const { return *Value; }
446 void setValue(const MCExpr *Expr) { Value = Expr; }
447
448 bool isSigned() const { return IsSigned; }
449
450 /// @}
451
452 static bool classof(const MCFragment *F) {
453 return F->getKind() == MCFragment::FT_LEB;
454 }
455};
456
457class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
458 /// The value of the difference between the two line numbers
459 /// between two .loc dwarf directives.
460 int64_t LineDelta;
461
462 /// The expression for the difference of the two symbols that
463 /// make up the address delta between two .loc dwarf directives.
464 const MCExpr *AddrDelta;
465
466public:
467 MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
468 MCSection *Sec = nullptr)
469 : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec),
470 LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
471
472 int64_t getLineDelta() const { return LineDelta; }
473
474 const MCExpr &getAddrDelta() const { return *AddrDelta; }
475
476 static bool classof(const MCFragment *F) {
477 return F->getKind() == MCFragment::FT_Dwarf;
478 }
479};
480
481class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
482 /// The expression for the difference of the two symbols that
483 /// make up the address delta between two .cfi_* dwarf directives.
484 const MCExpr *AddrDelta;
485
486public:
487 MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
488 : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec),
489 AddrDelta(&AddrDelta) {}
490
491 const MCExpr &getAddrDelta() const { return *AddrDelta; }
492 void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
493
494 static bool classof(const MCFragment *F) {
495 return F->getKind() == MCFragment::FT_DwarfFrame;
496 }
497};
498
499/// Represents a symbol table index fragment.
500class MCSymbolIdFragment : public MCFragment {
501 const MCSymbol *Sym;
502
503public:
504 MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
505 : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
506
507 const MCSymbol *getSymbol() { return Sym; }
508 const MCSymbol *getSymbol() const { return Sym; }
509
510 static bool classof(const MCFragment *F) {
511 return F->getKind() == MCFragment::FT_SymbolId;
512 }
513};
514
515/// Fragment representing the binary annotations produced by the
516/// .cv_inline_linetable directive.
517class MCCVInlineLineTableFragment : public MCFragment {
518 unsigned SiteFuncId;
519 unsigned StartFileId;
520 unsigned StartLineNum;
521 const MCSymbol *FnStartSym;
522 const MCSymbol *FnEndSym;
523 SmallString<8> Contents;
524
525 /// CodeViewContext has the real knowledge about this format, so let it access
526 /// our members.
527 friend class CodeViewContext;
528
529public:
530 MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
531 unsigned StartLineNum, const MCSymbol *FnStartSym,
532 const MCSymbol *FnEndSym,
533 MCSection *Sec = nullptr)
534 : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
535 StartFileId(StartFileId), StartLineNum(StartLineNum),
536 FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
537
538 const MCSymbol *getFnStartSym() const { return FnStartSym; }
539 const MCSymbol *getFnEndSym() const { return FnEndSym; }
540
541 SmallString<8> &getContents() { return Contents; }
542 const SmallString<8> &getContents() const { return Contents; }
543
544 static bool classof(const MCFragment *F) {
545 return F->getKind() == MCFragment::FT_CVInlineLines;
546 }
547};
548
549/// Fragment representing the .cv_def_range directive.
550class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
551 SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
552 SmallString<32> FixedSizePortion;
553
554 /// CodeViewContext has the real knowledge about this format, so let it access
555 /// our members.
556 friend class CodeViewContext;
557
558public:
559 MCCVDefRangeFragment(
560 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
561 StringRef FixedSizePortion, MCSection *Sec = nullptr)
562 : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec),
563 Ranges(Ranges.begin(), Ranges.end()),
564 FixedSizePortion(FixedSizePortion) {}
565
566 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
567 return Ranges;
568 }
569
570 StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
571
572 static bool classof(const MCFragment *F) {
573 return F->getKind() == MCFragment::FT_CVDefRange;
574 }
575};
576
577/// Represents required padding such that a particular other set of fragments
578/// does not cross a particular power-of-two boundary. The other fragments must
579/// follow this one within the same section.
580class MCBoundaryAlignFragment : public MCFragment {
581 /// The alignment requirement of the branch to be aligned.
582 Align AlignBoundary;
583 /// The last fragment in the set of fragments to be aligned.
584 const MCFragment *LastFragment = nullptr;
585 /// The size of the fragment. The size is lazily set during relaxation, and
586 /// is not meaningful before that.
587 uint64_t Size = 0;
588
589 /// When emitting Nops some subtargets have specific nop encodings.
590 const MCSubtargetInfo &STI;
591
592public:
593 MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI,
594 MCSection *Sec = nullptr)
595 : MCFragment(FT_BoundaryAlign, false, Sec), AlignBoundary(AlignBoundary),
596 STI(STI) {}
597
598 uint64_t getSize() const { return Size; }
599 void setSize(uint64_t Value) { Size = Value; }
600
601 Align getAlignment() const { return AlignBoundary; }
602 void setAlignment(Align Value) { AlignBoundary = Value; }
603
604 const MCFragment *getLastFragment() const { return LastFragment; }
605 void setLastFragment(const MCFragment *F) {
606 assert(!F || getParent() == F->getParent());
607 LastFragment = F;
608 }
609
610 const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
611
612 static bool classof(const MCFragment *F) {
613 return F->getKind() == MCFragment::FT_BoundaryAlign;
614 }
615};
616
617class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
618 /// The expression for the difference of the two symbols that
619 /// make up the address delta between two .pseudoprobe directives.
620 const MCExpr *AddrDelta;
621
622public:
623 MCPseudoProbeAddrFragment(const MCExpr *AddrDelta, MCSection *Sec = nullptr)
624 : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false, Sec),
625 AddrDelta(AddrDelta) {}
626
627 const MCExpr &getAddrDelta() const { return *AddrDelta; }
628
629 static bool classof(const MCFragment *F) {
630 return F->getKind() == MCFragment::FT_PseudoProbe;
631 }
632};
633} // end namespace llvm
634
635#endif // LLVM_MC_MCFRAGMENT_H
636

source code of llvm/include/llvm/MC/MCFragment.h