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