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 | |
24 | namespace llvm { |
25 | |
26 | class MCSection; |
27 | class MCSubtargetInfo; |
28 | class MCSymbol; |
29 | |
30 | class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> { |
31 | friend class MCAsmLayout; |
32 | |
33 | public: |
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 | |
53 | private: |
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 | |
76 | protected: |
77 | bool HasInstructions; |
78 | bool LinkerRelaxable = false; |
79 | |
80 | MCFragment(FragmentType Kind, bool HasInstructions, |
81 | MCSection *Parent = nullptr); |
82 | |
83 | public: |
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 | |
115 | class MCDummyFragment : public MCFragment { |
116 | public: |
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 | /// |
125 | class 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 | |
131 | protected: |
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 | |
140 | public: |
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 | /// |
186 | template<unsigned ContentsSize> |
187 | class MCEncodedFragmentWithContents : public MCEncodedFragment { |
188 | SmallVector<char, ContentsSize> Contents; |
189 | |
190 | protected: |
191 | MCEncodedFragmentWithContents(MCFragment::FragmentType FType, |
192 | bool HasInstructions, |
193 | MCSection *Sec) |
194 | : MCEncodedFragment(FType, HasInstructions, Sec) {} |
195 | |
196 | public: |
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 | /// |
204 | template<unsigned ContentsSize, unsigned FixupsSize> |
205 | class MCEncodedFragmentWithFixups : |
206 | public MCEncodedFragmentWithContents<ContentsSize> { |
207 | |
208 | /// The list of fixups in this fragment. |
209 | SmallVector<MCFixup, FixupsSize> Fixups; |
210 | |
211 | protected: |
212 | MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, |
213 | bool HasInstructions, |
214 | MCSection *Sec) |
215 | : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions, |
216 | Sec) {} |
217 | |
218 | public: |
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 | /// |
242 | class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { |
243 | public: |
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 | /// |
260 | class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> { |
261 | public: |
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 | /// |
274 | class 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 | |
281 | public: |
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 | |
298 | class 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 | |
320 | public: |
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 | |
347 | class 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 | |
357 | public: |
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 | |
374 | class 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 | |
386 | public: |
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 | |
404 | class 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 | |
414 | public: |
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 | |
431 | class 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 | |
438 | public: |
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 | |
457 | class 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 | |
466 | public: |
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 | |
481 | class 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 | |
486 | public: |
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. |
500 | class MCSymbolIdFragment : public MCFragment { |
501 | const MCSymbol *Sym; |
502 | |
503 | public: |
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. |
517 | class 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 | |
529 | public: |
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. |
550 | class 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 | |
558 | public: |
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. |
580 | class 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 | |
592 | public: |
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 | |
617 | class 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 | |
622 | public: |
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 | |