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