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 |