File indexing completed on 2026-05-10 08:44:13
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_MC_MCFRAGMENT_H
0010 #define LLVM_MC_MCFRAGMENT_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/SmallString.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/ADT/StringRef.h"
0016 #include "llvm/ADT/ilist_node.h"
0017 #include "llvm/MC/MCFixup.h"
0018 #include "llvm/MC/MCInst.h"
0019 #include "llvm/Support/Alignment.h"
0020 #include "llvm/Support/SMLoc.h"
0021 #include <cstdint>
0022 #include <utility>
0023
0024 namespace llvm {
0025
0026 class MCAssembler;
0027 class MCObjectStreamer;
0028 class MCSection;
0029 class MCSubtargetInfo;
0030 class MCSymbol;
0031
0032 class MCFragment {
0033 friend class MCAssembler;
0034 friend class MCObjectStreamer;
0035 friend class MCSection;
0036
0037 public:
0038 enum FragmentType : uint8_t {
0039 FT_Align,
0040 FT_Data,
0041 FT_Fill,
0042 FT_Nops,
0043 FT_Relaxable,
0044 FT_Org,
0045 FT_Dwarf,
0046 FT_DwarfFrame,
0047 FT_LEB,
0048 FT_BoundaryAlign,
0049 FT_SymbolId,
0050 FT_CVInlineLines,
0051 FT_CVDefRange,
0052 FT_PseudoProbe,
0053 FT_Dummy
0054 };
0055
0056 private:
0057
0058 MCFragment *Next = nullptr;
0059
0060
0061 MCSection *Parent = nullptr;
0062
0063
0064 uint64_t Offset = 0;
0065
0066
0067 unsigned LayoutOrder = 0;
0068
0069 FragmentType Kind;
0070
0071 protected:
0072
0073
0074
0075 bool HasInstructions : 1;
0076 bool AlignToBundleEnd : 1;
0077
0078 bool LinkerRelaxable : 1;
0079
0080 bool AllowAutoPadding : 1;
0081
0082 MCFragment(FragmentType Kind, bool HasInstructions);
0083
0084 public:
0085 MCFragment() = delete;
0086 MCFragment(const MCFragment &) = delete;
0087 MCFragment &operator=(const MCFragment &) = delete;
0088
0089
0090
0091
0092
0093 void destroy();
0094
0095 MCFragment *getNext() const { return Next; }
0096
0097 FragmentType getKind() const { return Kind; }
0098
0099 MCSection *getParent() const { return Parent; }
0100 void setParent(MCSection *Value) { Parent = Value; }
0101
0102 const MCSymbol *getAtom() const;
0103
0104 unsigned getLayoutOrder() const { return LayoutOrder; }
0105 void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
0106
0107
0108
0109 bool hasInstructions() const { return HasInstructions; }
0110
0111 void dump() const;
0112 };
0113
0114 class MCDummyFragment : public MCFragment {
0115 public:
0116 explicit MCDummyFragment() : MCFragment(FT_Dummy, false) {}
0117
0118 static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
0119 };
0120
0121
0122
0123
0124 class MCEncodedFragment : public MCFragment {
0125 uint8_t BundlePadding = 0;
0126
0127 protected:
0128 MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions)
0129 : MCFragment(FType, HasInstructions) {}
0130
0131
0132
0133 const MCSubtargetInfo *STI = nullptr;
0134
0135 public:
0136 static bool classof(const MCFragment *F) {
0137 MCFragment::FragmentType Kind = F->getKind();
0138 switch (Kind) {
0139 default:
0140 return false;
0141 case MCFragment::FT_Relaxable:
0142 case MCFragment::FT_Data:
0143 case MCFragment::FT_Dwarf:
0144 case MCFragment::FT_DwarfFrame:
0145 case MCFragment::FT_PseudoProbe:
0146 return true;
0147 }
0148 }
0149
0150
0151 bool alignToBundleEnd() const { return AlignToBundleEnd; }
0152 void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
0153
0154
0155
0156
0157
0158
0159 uint8_t getBundlePadding() const { return BundlePadding; }
0160
0161
0162
0163 void setBundlePadding(uint8_t N) { BundlePadding = N; }
0164
0165
0166
0167 const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
0168
0169
0170
0171 void setHasInstructions(const MCSubtargetInfo &STI) {
0172 HasInstructions = true;
0173 this->STI = &STI;
0174 }
0175 };
0176
0177
0178
0179
0180 template <unsigned ContentsSize, unsigned FixupsSize>
0181 class MCEncodedFragmentWithFixups : public MCEncodedFragment {
0182 SmallVector<char, ContentsSize> Contents;
0183
0184
0185 SmallVector<MCFixup, FixupsSize> Fixups;
0186
0187 protected:
0188 MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
0189 bool HasInstructions)
0190 : MCEncodedFragment(FType, HasInstructions) {}
0191
0192 public:
0193 SmallVectorImpl<char> &getContents() { return Contents; }
0194 const SmallVectorImpl<char> &getContents() const { return Contents; }
0195
0196 void appendContents(ArrayRef<char> C) { Contents.append(C.begin(), C.end()); }
0197 void appendContents(size_t Num, char Elt) { Contents.append(Num, Elt); }
0198 void setContents(ArrayRef<char> C) { Contents.assign(C.begin(), C.end()); }
0199
0200 SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
0201 const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
0202
0203 static bool classof(const MCFragment *F) {
0204 MCFragment::FragmentType Kind = F->getKind();
0205 return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
0206 Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf ||
0207 Kind == MCFragment::FT_DwarfFrame;
0208 }
0209 };
0210
0211
0212
0213 class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
0214 public:
0215 MCDataFragment() : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false) {}
0216
0217 static bool classof(const MCFragment *F) {
0218 return F->getKind() == MCFragment::FT_Data;
0219 }
0220
0221 bool isLinkerRelaxable() const { return LinkerRelaxable; }
0222 void setLinkerRelaxable() { LinkerRelaxable = true; }
0223 };
0224
0225
0226
0227
0228 class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
0229
0230 MCInst Inst;
0231
0232 public:
0233 MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI)
0234 : MCEncodedFragmentWithFixups(FT_Relaxable, true), Inst(Inst) {
0235 this->STI = &STI;
0236 }
0237
0238 const MCInst &getInst() const { return Inst; }
0239 void setInst(const MCInst &Value) { Inst = Value; }
0240
0241 bool getAllowAutoPadding() const { return AllowAutoPadding; }
0242 void setAllowAutoPadding(bool V) { AllowAutoPadding = V; }
0243
0244 static bool classof(const MCFragment *F) {
0245 return F->getKind() == MCFragment::FT_Relaxable;
0246 }
0247 };
0248
0249 class MCAlignFragment : public MCFragment {
0250
0251 Align Alignment;
0252
0253
0254
0255
0256 bool EmitNops : 1;
0257
0258
0259 int64_t Value;
0260
0261
0262 unsigned ValueSize;
0263
0264
0265
0266 unsigned MaxBytesToEmit;
0267
0268
0269 const MCSubtargetInfo *STI = nullptr;
0270
0271 public:
0272 MCAlignFragment(Align Alignment, int64_t Value, unsigned ValueSize,
0273 unsigned MaxBytesToEmit)
0274 : MCFragment(FT_Align, false), Alignment(Alignment), EmitNops(false),
0275 Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
0276
0277 Align getAlignment() const { return Alignment; }
0278
0279 int64_t getValue() const { return Value; }
0280
0281 unsigned getValueSize() const { return ValueSize; }
0282
0283 unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
0284
0285 bool hasEmitNops() const { return EmitNops; }
0286 void setEmitNops(bool Value, const MCSubtargetInfo *STI) {
0287 EmitNops = Value;
0288 this->STI = STI;
0289 }
0290
0291 const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
0292
0293 static bool classof(const MCFragment *F) {
0294 return F->getKind() == MCFragment::FT_Align;
0295 }
0296 };
0297
0298 class MCFillFragment : public MCFragment {
0299 uint8_t ValueSize;
0300
0301 uint64_t Value;
0302
0303 const MCExpr &NumValues;
0304
0305
0306 SMLoc Loc;
0307
0308 public:
0309 MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
0310 SMLoc Loc)
0311 : MCFragment(FT_Fill, false), ValueSize(VSize), Value(Value),
0312 NumValues(NumValues), Loc(Loc) {}
0313
0314 uint64_t getValue() const { return Value; }
0315 uint8_t getValueSize() const { return ValueSize; }
0316 const MCExpr &getNumValues() const { return NumValues; }
0317
0318 SMLoc getLoc() const { return Loc; }
0319
0320 static bool classof(const MCFragment *F) {
0321 return F->getKind() == MCFragment::FT_Fill;
0322 }
0323 };
0324
0325 class MCNopsFragment : public MCFragment {
0326
0327 int64_t Size;
0328
0329 int64_t ControlledNopLength;
0330
0331
0332 SMLoc Loc;
0333
0334
0335 const MCSubtargetInfo &STI;
0336
0337 public:
0338 MCNopsFragment(int64_t NumBytes, int64_t ControlledNopLength, SMLoc L,
0339 const MCSubtargetInfo &STI)
0340 : MCFragment(FT_Nops, false), Size(NumBytes),
0341 ControlledNopLength(ControlledNopLength), Loc(L), STI(STI) {}
0342
0343 int64_t getNumBytes() const { return Size; }
0344 int64_t getControlledNopLength() const { return ControlledNopLength; }
0345
0346 SMLoc getLoc() const { return Loc; }
0347
0348 const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
0349
0350 static bool classof(const MCFragment *F) {
0351 return F->getKind() == MCFragment::FT_Nops;
0352 }
0353 };
0354
0355 class MCOrgFragment : public MCFragment {
0356
0357 int8_t Value;
0358
0359
0360 const MCExpr *Offset;
0361
0362
0363 SMLoc Loc;
0364
0365 public:
0366 MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc)
0367 : MCFragment(FT_Org, false), Value(Value), Offset(&Offset), Loc(Loc) {}
0368
0369 const MCExpr &getOffset() const { return *Offset; }
0370
0371 uint8_t getValue() const { return Value; }
0372
0373 SMLoc getLoc() const { return Loc; }
0374
0375 static bool classof(const MCFragment *F) {
0376 return F->getKind() == MCFragment::FT_Org;
0377 }
0378 };
0379
0380 class MCLEBFragment final : public MCEncodedFragmentWithFixups<8, 0> {
0381
0382 bool IsSigned;
0383
0384
0385 const MCExpr *Value;
0386
0387 public:
0388 MCLEBFragment(const MCExpr &Value, bool IsSigned)
0389 : MCEncodedFragmentWithFixups<8, 0>(FT_LEB, false), IsSigned(IsSigned),
0390 Value(&Value) {
0391 getContents().push_back(0);
0392 }
0393
0394 const MCExpr &getValue() const { return *Value; }
0395 void setValue(const MCExpr *Expr) { Value = Expr; }
0396
0397 bool isSigned() const { return IsSigned; }
0398
0399
0400
0401 static bool classof(const MCFragment *F) {
0402 return F->getKind() == MCFragment::FT_LEB;
0403 }
0404 };
0405
0406 class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
0407
0408
0409 int64_t LineDelta;
0410
0411
0412
0413 const MCExpr *AddrDelta;
0414
0415 public:
0416 MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta)
0417 : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false),
0418 LineDelta(LineDelta), AddrDelta(&AddrDelta) {}
0419
0420 int64_t getLineDelta() const { return LineDelta; }
0421
0422 const MCExpr &getAddrDelta() const { return *AddrDelta; }
0423
0424 static bool classof(const MCFragment *F) {
0425 return F->getKind() == MCFragment::FT_Dwarf;
0426 }
0427 };
0428
0429 class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> {
0430
0431
0432 const MCExpr *AddrDelta;
0433
0434 public:
0435 MCDwarfCallFrameFragment(const MCExpr &AddrDelta)
0436 : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false),
0437 AddrDelta(&AddrDelta) {}
0438
0439 const MCExpr &getAddrDelta() const { return *AddrDelta; }
0440 void setAddrDelta(const MCExpr *E) { AddrDelta = E; }
0441
0442 static bool classof(const MCFragment *F) {
0443 return F->getKind() == MCFragment::FT_DwarfFrame;
0444 }
0445 };
0446
0447
0448 class MCSymbolIdFragment : public MCFragment {
0449 const MCSymbol *Sym;
0450
0451 public:
0452 MCSymbolIdFragment(const MCSymbol *Sym)
0453 : MCFragment(FT_SymbolId, false), Sym(Sym) {}
0454
0455 const MCSymbol *getSymbol() { return Sym; }
0456 const MCSymbol *getSymbol() const { return Sym; }
0457
0458 static bool classof(const MCFragment *F) {
0459 return F->getKind() == MCFragment::FT_SymbolId;
0460 }
0461 };
0462
0463
0464
0465 class MCCVInlineLineTableFragment : public MCFragment {
0466 unsigned SiteFuncId;
0467 unsigned StartFileId;
0468 unsigned StartLineNum;
0469 const MCSymbol *FnStartSym;
0470 const MCSymbol *FnEndSym;
0471 SmallString<8> Contents;
0472
0473
0474
0475 friend class CodeViewContext;
0476
0477 public:
0478 MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
0479 unsigned StartLineNum, const MCSymbol *FnStartSym,
0480 const MCSymbol *FnEndSym)
0481 : MCFragment(FT_CVInlineLines, false), SiteFuncId(SiteFuncId),
0482 StartFileId(StartFileId), StartLineNum(StartLineNum),
0483 FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}
0484
0485 const MCSymbol *getFnStartSym() const { return FnStartSym; }
0486 const MCSymbol *getFnEndSym() const { return FnEndSym; }
0487
0488 SmallString<8> &getContents() { return Contents; }
0489 const SmallString<8> &getContents() const { return Contents; }
0490
0491 static bool classof(const MCFragment *F) {
0492 return F->getKind() == MCFragment::FT_CVInlineLines;
0493 }
0494 };
0495
0496
0497 class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> {
0498 SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges;
0499 SmallString<32> FixedSizePortion;
0500
0501
0502
0503 friend class CodeViewContext;
0504
0505 public:
0506 MCCVDefRangeFragment(
0507 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
0508 StringRef FixedSizePortion)
0509 : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false),
0510 Ranges(Ranges), FixedSizePortion(FixedSizePortion) {}
0511
0512 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const {
0513 return Ranges;
0514 }
0515
0516 StringRef getFixedSizePortion() const { return FixedSizePortion.str(); }
0517
0518 static bool classof(const MCFragment *F) {
0519 return F->getKind() == MCFragment::FT_CVDefRange;
0520 }
0521 };
0522
0523
0524
0525
0526 class MCBoundaryAlignFragment : public MCFragment {
0527
0528 Align AlignBoundary;
0529
0530 const MCFragment *LastFragment = nullptr;
0531
0532
0533 uint64_t Size = 0;
0534
0535
0536 const MCSubtargetInfo &STI;
0537
0538 public:
0539 MCBoundaryAlignFragment(Align AlignBoundary, const MCSubtargetInfo &STI)
0540 : MCFragment(FT_BoundaryAlign, false), AlignBoundary(AlignBoundary),
0541 STI(STI) {}
0542
0543 uint64_t getSize() const { return Size; }
0544 void setSize(uint64_t Value) { Size = Value; }
0545
0546 Align getAlignment() const { return AlignBoundary; }
0547 void setAlignment(Align Value) { AlignBoundary = Value; }
0548
0549 const MCFragment *getLastFragment() const { return LastFragment; }
0550 void setLastFragment(const MCFragment *F) {
0551 assert(!F || getParent() == F->getParent());
0552 LastFragment = F;
0553 }
0554
0555 const MCSubtargetInfo *getSubtargetInfo() const { return &STI; }
0556
0557 static bool classof(const MCFragment *F) {
0558 return F->getKind() == MCFragment::FT_BoundaryAlign;
0559 }
0560 };
0561
0562 class MCPseudoProbeAddrFragment : public MCEncodedFragmentWithFixups<8, 1> {
0563
0564
0565 const MCExpr *AddrDelta;
0566
0567 public:
0568 MCPseudoProbeAddrFragment(const MCExpr *AddrDelta)
0569 : MCEncodedFragmentWithFixups<8, 1>(FT_PseudoProbe, false),
0570 AddrDelta(AddrDelta) {}
0571
0572 const MCExpr &getAddrDelta() const { return *AddrDelta; }
0573
0574 static bool classof(const MCFragment *F) {
0575 return F->getKind() == MCFragment::FT_PseudoProbe;
0576 }
0577 };
0578 }
0579
0580 #endif