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