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 |