From f3b795b3402c37bf29b68aadc6158158101ccfca Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 13 Jul 2025 11:54:21 -0700 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?= =?UTF-8?q?l=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.5-bogner --- llvm/include/llvm/MC/MCAsmBackend.h | 16 +- llvm/include/llvm/MC/MCAssembler.h | 18 +- llvm/include/llvm/MC/MCCodeView.h | 3 +- llvm/include/llvm/MC/MCContext.h | 3 +- llvm/include/llvm/MC/MCELFStreamer.h | 3 +- llvm/include/llvm/MC/MCObjectStreamer.h | 6 +- llvm/include/llvm/MC/MCSection.h | 309 +++++++++--------- llvm/lib/MC/MCAsmBackend.cpp | 9 +- llvm/lib/MC/MCAssembler.cpp | 129 ++++---- llvm/lib/MC/MCELFStreamer.cpp | 4 +- llvm/lib/MC/MCExpr.cpp | 8 +- llvm/lib/MC/MCFragment.cpp | 93 +++--- llvm/lib/MC/MCObjectStreamer.cpp | 69 ++-- llvm/lib/MC/MCSection.cpp | 34 +- llvm/lib/MC/WasmObjectWriter.cpp | 6 +- .../MCTargetDesc/AArch64ELFStreamer.cpp | 8 +- .../Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 3 +- .../Target/ARM/MCTargetDesc/ARMAsmBackend.h | 3 +- .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 11 +- .../CSKY/MCTargetDesc/CSKYAsmBackend.cpp | 3 +- .../Target/CSKY/MCTargetDesc/CSKYAsmBackend.h | 3 +- .../MCTargetDesc/HexagonAsmBackend.cpp | 15 +- .../MCTargetDesc/LoongArchAsmBackend.cpp | 33 +- .../MCTargetDesc/LoongArchAsmBackend.h | 8 +- .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 45 ++- .../RISCV/MCTargetDesc/RISCVAsmBackend.h | 11 +- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 58 ++-- llvm/test/MC/ELF/mc-dump.s | 22 +- 28 files changed, 486 insertions(+), 447 deletions(-) diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h index 6b81bdba25e67..9a4862baaeb3a 100644 --- a/llvm/include/llvm/MC/MCAsmBackend.h +++ b/llvm/include/llvm/MC/MCAsmBackend.h @@ -19,11 +19,8 @@ namespace llvm { class MCAlignFragment; -class MCDwarfCallFrameFragment; -class MCDwarfLineAddrFragment; class MCFragment; class MCLEBFragment; -class MCRelaxableFragment; class MCSymbol; class MCAssembler; class MCContext; @@ -157,8 +154,9 @@ class LLVM_ABI MCAsmBackend { /// Target specific predicate for whether a given fixup requires the /// associated instruction to be relaxed. - virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, - uint64_t, bool Resolved) const; + virtual bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, + bool Resolved) const; /// Simple predicate for targets where !Resolved implies requiring relaxation virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, @@ -179,18 +177,16 @@ class LLVM_ABI MCAsmBackend { } // Defined by linker relaxation targets. - virtual bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, - bool &WasRelaxed) const { + virtual bool relaxDwarfLineAddr(MCFragment &, bool &WasRelaxed) const { return false; } - virtual bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const { + virtual bool relaxDwarfCFA(MCFragment &, bool &WasRelaxed) const { return false; } // Defined by linker relaxation targets to possibly emit LEB128 relocations // and set Value at the relocated location. - virtual std::pair relaxLEB128(MCLEBFragment &LF, + virtual std::pair relaxLEB128(MCFragment &, int64_t &Value) const { return std::make_pair(false, false); } diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 1015992cedf29..858596ff8757c 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -34,13 +34,10 @@ namespace llvm { class MCBoundaryAlignFragment; class MCCVDefRangeFragment; class MCCVInlineLineTableFragment; -class MCDwarfCallFrameFragment; -class MCDwarfLineAddrFragment; -class MCEncodedFragment; +class MCFragment; class MCFixup; class MCLEBFragment; class MCPseudoProbeAddrFragment; -class MCRelaxableFragment; class MCSymbolRefExpr; class raw_ostream; class MCAsmBackend; @@ -107,7 +104,7 @@ class MCAssembler { /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). - bool fixupNeedsRelaxation(const MCRelaxableFragment &, const MCFixup &) const; + bool fixupNeedsRelaxation(const MCFragment &, const MCFixup &) const; void layoutSection(MCSection &Sec); /// Perform one layout iteration and return the index of the first stable @@ -116,11 +113,11 @@ class MCAssembler { /// Perform relaxation on a single fragment. bool relaxFragment(MCFragment &F); - bool relaxInstruction(MCRelaxableFragment &IF); - bool relaxLEB(MCLEBFragment &IF); + bool relaxInstruction(MCFragment &F); + bool relaxLEB(MCFragment &F); bool relaxBoundaryAlign(MCBoundaryAlignFragment &BF); - bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF); - bool relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF); + bool relaxDwarfLineAddr(MCFragment &F); + bool relaxDwarfCallFrameFragment(MCFragment &F); bool relaxCVInlineLineTable(MCCVInlineLineTableFragment &DF); bool relaxCVDefRange(MCCVDefRangeFragment &DF); bool relaxFill(MCFillFragment &F); @@ -228,8 +225,7 @@ class MCAssembler { /// Write the necessary bundle padding to \p OS. /// Expects a fragment \p F containing instructions and its size \p FSize. - LLVM_ABI void writeFragmentPadding(raw_ostream &OS, - const MCEncodedFragment &F, + LLVM_ABI void writeFragmentPadding(raw_ostream &OS, const MCFragment &F, uint64_t FSize) const; LLVM_ABI void reportError(SMLoc L, const Twine &Msg) const; diff --git a/llvm/include/llvm/MC/MCCodeView.h b/llvm/include/llvm/MC/MCCodeView.h index 88f84a2462841..9cde44c71baff 100644 --- a/llvm/include/llvm/MC/MCCodeView.h +++ b/llvm/include/llvm/MC/MCCodeView.h @@ -26,7 +26,6 @@ namespace llvm { class MCAssembler; class MCCVDefRangeFragment; class MCCVInlineLineTableFragment; -class MCDataFragment; class MCFragment; class MCSection; class MCSymbol; @@ -231,7 +230,7 @@ class CodeViewContext { StringMap StringTable; /// The fragment that ultimately holds our strings. - MCDataFragment *StrTabFragment = nullptr; + MCFragment *StrTabFragment = nullptr; SmallVector StrTab = {'\0'}; /// Get a string table offset. diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 5a8ec17dae1cc..c137f6184a9a7 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -47,7 +47,6 @@ namespace llvm { class CodeViewContext; class MCAsmInfo; -class MCDataFragment; class MCInst; class MCLabel; class MCObjectFileInfo; @@ -334,7 +333,7 @@ class MCContext { void reportCommon(SMLoc Loc, std::function); - MCDataFragment *allocInitialFragment(MCSection &Sec); + MCFragment *allocInitialFragment(MCSection &Sec); MCSymbolTableEntry &getSymbolTableEntry(StringRef Name); diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h index aba87cb19b21c..5affe206a3535 100644 --- a/llvm/include/llvm/MC/MCELFStreamer.h +++ b/llvm/include/llvm/MC/MCELFStreamer.h @@ -17,7 +17,6 @@ namespace llvm { class ELFObjectWriter; class MCContext; -class MCDataFragment; class MCFragment; class MCObjectWriter; class MCSection; @@ -51,7 +50,7 @@ class MCELFStreamer : public MCObjectStreamer { void initSections(bool NoExecStack, const MCSubtargetInfo &STI) override; void changeSection(MCSection *Section, uint32_t Subsection = 0) override; void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; - void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F, + void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCFragment &F, uint64_t Offset) override; void emitWeakReference(MCSymbol *Alias, const MCSymbol *Target) override; bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 58c18af406158..f8635fb989417 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -43,8 +43,8 @@ class MCObjectStreamer : public MCStreamer { struct PendingMCFixup { const MCSymbol *Sym; MCFixup Fixup; - MCDataFragment *DF; - PendingMCFixup(const MCSymbol *McSym, MCDataFragment *F, MCFixup McFixup) + MCFragment *DF; + PendingMCFixup(const MCSymbol *McSym, MCFragment *F, MCFixup McFixup) : Sym(McSym), Fixup(McFixup), DF(F) {} }; SmallVector PendingFixups; @@ -95,7 +95,7 @@ class MCObjectStreamer : public MCStreamer { /// fragment is not a data fragment. /// Optionally a \p STI can be passed in so that a new fragment is created /// if the Subtarget differs from the current fragment. - MCDataFragment *getOrCreateDataFragment(const MCSubtargetInfo* STI = nullptr); + MCFragment *getOrCreateDataFragment(const MCSubtargetInfo *STI = nullptr); protected: bool changeSectionImpl(MCSection *Section, uint32_t Subsection); diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 16d57a7772a40..e018e98d66151 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -46,8 +46,6 @@ class LLVM_ABI MCSection { friend MCAssembler; friend MCObjectStreamer; friend class MCFragment; - friend class MCEncodedFragment; - friend class MCRelaxableFragment; static constexpr unsigned NonUniqueID = ~0U; enum SectionVariant { @@ -265,55 +263,55 @@ class MCFragment { /// MCRelaxableFragment: x86-specific bool AllowAutoPadding : 1; - LLVM_ABI MCFragment(FragmentType Kind, bool HasInstructions); - -public: - MCFragment() = delete; - MCFragment(const MCFragment &) = delete; - MCFragment &operator=(const MCFragment &) = delete; - - MCFragment *getNext() const { return Next; } - - FragmentType getKind() const { return Kind; } - - MCSection *getParent() const { return Parent; } - void setParent(MCSection *Value) { Parent = Value; } - - LLVM_ABI const MCSymbol *getAtom() const; - - unsigned getLayoutOrder() const { return LayoutOrder; } - void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } - - /// Does this fragment have instructions emitted into it? By default - /// this is false, but specific fragment types may set it to true. - bool hasInstructions() const { return HasInstructions; } - - bool isLinkerRelaxable() const { return LinkerRelaxable; } - void setLinkerRelaxable() { LinkerRelaxable = true; } - - LLVM_ABI void dump() const; -}; - -/// Interface implemented by fragments that contain encoded instructions and/or -/// data. -class MCEncodedFragment : public MCFragment { uint8_t BundlePadding = 0; + uint32_t ContentStart = 0; uint32_t ContentEnd = 0; uint32_t FixupStart = 0; uint32_t FixupEnd = 0; -protected: - MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions) - : MCFragment(FType, HasInstructions) {} + uint32_t VarContentStart = 0; + uint32_t VarContentEnd = 0; + uint32_t VarFixupStart = 0; + uint32_t VarFixupEnd = 0; - /// The MCSubtargetInfo in effect when the instruction was encoded. - /// It must be non-null for instructions. const MCSubtargetInfo *STI = nullptr; + // Optional variable-size tail used by various fragment types. + union Tail { + struct { + uint32_t Opcode; + uint32_t Flags; + uint32_t OperandStart; + uint32_t OperandSize; + } relax; + struct { + // True if this is a sleb128, false if uleb128. + bool IsSigned; + // The value this fragment should contain. + const MCExpr *Value; + } leb; + struct { + const MCExpr *AddrDelta; + } dwarf_frame; + struct { + // The expression for the difference of the two symbols that make up the + // address delta between two .loc dwarf directives. + const MCExpr *AddrDelta; + // The value of the difference between the two line numbers between two + // .loc dwarf directives. + int64_t LineDelta; + } dwarf; + } u{}; + public: - static bool classof(const MCFragment *F) { - MCFragment::FragmentType Kind = F->getKind(); + LLVM_ABI MCFragment(FragmentType Kind = MCFragment::FT_Data, + bool HasInstructions = false); + MCFragment(const MCFragment &) = delete; + MCFragment &operator=(const MCFragment &) = delete; + + bool isEncoded() const { + MCFragment::FragmentType Kind = getKind(); switch (Kind) { default: return false; @@ -329,20 +327,23 @@ class MCEncodedFragment : public MCFragment { } } - /// Should this fragment be placed at the end of an aligned bundle? - bool alignToBundleEnd() const { return AlignToBundleEnd; } - void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + MCFragment *getNext() const { return Next; } - /// Get the padding size that must be inserted before this fragment. - /// Used for bundling. By default, no padding is inserted. - /// Note that padding size is restricted to 8 bits. This is an optimization - /// to reduce the amount of space used for each fragment. In practice, larger - /// padding should never be required. - uint8_t getBundlePadding() const { return BundlePadding; } + FragmentType getKind() const { return Kind; } - /// Set the padding size for this fragment. By default it's a no-op, - /// and only some fragments have a meaningful implementation. - void setBundlePadding(uint8_t N) { BundlePadding = N; } + MCSection *getParent() const { return Parent; } + void setParent(MCSection *Value) { Parent = Value; } + + LLVM_ABI const MCSymbol *getAtom() const; + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + /// Does this fragment have instructions emitted into it? By default + /// this is false, but specific fragment types may set it to true. + bool hasInstructions() const { return HasInstructions; } + + LLVM_ABI void dump() const; /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. /// Guaranteed to be non-null if hasInstructions() == true @@ -355,9 +356,27 @@ class MCEncodedFragment : public MCFragment { this->STI = &STI; } + bool isLinkerRelaxable() const { return LinkerRelaxable; } + void setLinkerRelaxable() { LinkerRelaxable = true; } + bool getAllowAutoPadding() const { return AllowAutoPadding; } void setAllowAutoPadding(bool V) { AllowAutoPadding = V; } + /// Should this fragment be placed at the end of an aligned bundle? + bool alignToBundleEnd() const { return AlignToBundleEnd; } + void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + + /// Get the padding size that must be inserted before this fragment. + /// Used for bundling. By default, no padding is inserted. + /// Note that padding size is restricted to 8 bits. This is an optimization + /// to reduce the amount of space used for each fragment. In practice, larger + /// padding should never be required. + uint8_t getBundlePadding() const { return BundlePadding; } + + /// Set the padding size for this fragment. By default it's a no-op, + /// and only some fragments have a meaningful implementation. + void setBundlePadding(uint8_t N) { BundlePadding = N; } + // Content-related functions manage parent's storage using ContentStart and // ContentSize. void clearContents() { ContentEnd = ContentStart; } @@ -394,7 +413,24 @@ class MCEncodedFragment : public MCFragment { .slice(ContentStart, ContentEnd - ContentStart); } - // Fixup-related functions manage parent's storage using FixupStart and + void setVarContents(ArrayRef Contents); + void clearVarContents() { setVarContents({}); } + MutableArrayRef getVarContents() { + return MutableArrayRef(getParent()->ContentStorage) + .slice(VarContentStart, VarContentEnd - VarContentStart); + } + ArrayRef getVarContents() const { + return ArrayRef(getParent()->ContentStorage) + .slice(VarContentStart, VarContentEnd - VarContentStart); + } + + size_t getFixedSize() const { return ContentEnd - ContentStart; } + size_t getVarSize() const { return VarContentEnd - VarContentStart; } + size_t getSize() const { + return ContentEnd - ContentStart + (VarContentEnd - VarContentStart); + } + + //== Fixup-related functions manage parent's storage using FixupStart and // FixupSize. void clearFixups() { FixupEnd = FixupStart; } LLVM_ABI void addFixup(MCFixup Fixup); @@ -409,65 +445,91 @@ class MCEncodedFragment : public MCFragment { .slice(FixupStart, FixupEnd - FixupStart); } - size_t getSize() const { return ContentEnd - ContentStart; } -}; - -/// Fragment for data and encoded instructions. -/// -class MCDataFragment : public MCEncodedFragment { -public: - MCDataFragment() : MCEncodedFragment(FT_Data, false) {} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Data; + // Source fixup offsets are relative to the variable part's start. + // Stored fixup offsets are relative to the fixed part's start. + void setVarFixups(ArrayRef Fixups); + void clearVarFixups() { setVarFixups({}); } + MutableArrayRef getVarFixups() { + return MutableArrayRef(getParent()->FixupStorage) + .slice(VarFixupStart, VarFixupEnd - VarFixupStart); } -}; - -/// A relaxable fragment holds on to its MCInst, since it may need to be -/// relaxed during the assembler layout and relaxation stage. -/// -class MCRelaxableFragment : public MCEncodedFragment { - uint32_t Opcode = 0; - uint32_t Flags = 0; - uint32_t OperandStart = 0; - uint32_t OperandSize = 0; - -public: - MCRelaxableFragment(const MCSubtargetInfo &STI) - : MCEncodedFragment(FT_Relaxable, true) { - this->STI = &STI; + ArrayRef getVarFixups() const { + return ArrayRef(getParent()->FixupStorage) + .slice(VarFixupStart, VarFixupEnd - VarFixupStart); } - unsigned getOpcode() const { return Opcode; } + //== FT_Relaxable functions + unsigned getOpcode() const { + assert(Kind == FT_Relaxable); + return u.relax.Opcode; + } ArrayRef getOperands() const { + assert(Kind == FT_Relaxable); return MutableArrayRef(getParent()->MCOperandStorage) - .slice(OperandStart, OperandSize); + .slice(u.relax.OperandStart, u.relax.OperandSize); } MCInst getInst() const { + assert(Kind == FT_Relaxable); MCInst Inst; - Inst.setOpcode(Opcode); - Inst.setFlags(Flags); + Inst.setOpcode(u.relax.Opcode); + Inst.setFlags(u.relax.Flags); Inst.setOperands(ArrayRef(getParent()->MCOperandStorage) - .slice(OperandStart, OperandSize)); + .slice(u.relax.OperandStart, u.relax.OperandSize)); return Inst; } void setInst(const MCInst &Inst) { - Opcode = Inst.getOpcode(); - Flags = Inst.getFlags(); + assert(Kind == FT_Relaxable); + u.relax.Opcode = Inst.getOpcode(); + u.relax.Flags = Inst.getFlags(); auto &S = getParent()->MCOperandStorage; - if (Inst.getNumOperands() > OperandSize) { - OperandStart = S.size(); + if (Inst.getNumOperands() > u.relax.OperandSize) { + u.relax.OperandStart = S.size(); S.resize_for_overwrite(S.size() + Inst.getNumOperands()); } - OperandSize = Inst.getNumOperands(); - llvm::copy(Inst, S.begin() + OperandStart); + u.relax.OperandSize = Inst.getNumOperands(); + llvm::copy(Inst, S.begin() + u.relax.OperandStart); } - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Relaxable; + //== FT_LEB functions + const MCExpr &getLEBValue() const { + assert(Kind == FT_LEB); + return *u.leb.Value; } + void setLEBValue(const MCExpr *Expr) { u.leb.Value = Expr; } + bool isLEBSigned() const { return u.leb.IsSigned; } + void setLEBSigned(bool S) { u.leb.IsSigned = S; } + + //== FT_DwarfFrame functions + const MCExpr &getAddrDelta() const { + assert(Kind == FT_Dwarf || Kind == FT_DwarfFrame); + return *u.dwarf.AddrDelta; + } + void setAddrDelta(const MCExpr *E) { + assert(Kind == FT_Dwarf || Kind == FT_DwarfFrame); + u.dwarf.AddrDelta = E; + } + int64_t getLineDelta() const { + assert(Kind == FT_Dwarf); + return u.dwarf.LineDelta; + } + void setLineDelta(int64_t LineDelta) { + assert(Kind == FT_Dwarf); + u.dwarf.LineDelta = LineDelta; + } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data. +class MCEncodedFragment : public MCFragment { +protected: + MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions) + : MCFragment(FType, HasInstructions) {} }; +// TODO Delete +using MCDataFragment = MCFragment; +using MCRelaxableFragment = MCFragment; + class MCAlignFragment : public MCFragment { /// The alignment to ensure, in bytes. Align Alignment; @@ -602,67 +664,6 @@ class MCOrgFragment : public MCFragment { } }; -class MCLEBFragment final : public MCEncodedFragment { - /// True if this is a sleb128, false if uleb128. - bool IsSigned; - - /// The value this fragment should contain. - const MCExpr *Value; - -public: - MCLEBFragment(const MCExpr &Value, bool IsSigned) - : MCEncodedFragment(FT_LEB, false), IsSigned(IsSigned), Value(&Value) {} - - const MCExpr &getValue() const { return *Value; } - void setValue(const MCExpr *Expr) { Value = Expr; } - - bool isSigned() const { return IsSigned; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_LEB; - } -}; - -class MCDwarfLineAddrFragment : public MCEncodedFragment { - /// The value of the difference between the two line numbers - /// between two .loc dwarf directives. - int64_t LineDelta; - - /// The expression for the difference of the two symbols that - /// make up the address delta between two .loc dwarf directives. - const MCExpr *AddrDelta; - -public: - MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta) - : MCEncodedFragment(FT_Dwarf, false), LineDelta(LineDelta), - AddrDelta(&AddrDelta) {} - - int64_t getLineDelta() const { return LineDelta; } - - const MCExpr &getAddrDelta() const { return *AddrDelta; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_Dwarf; - } -}; - -class MCDwarfCallFrameFragment : public MCEncodedFragment { - /// The expression for the difference of the two symbols that - /// make up the address delta between two .cfi_* dwarf directives. - const MCExpr *AddrDelta; - -public: - MCDwarfCallFrameFragment(const MCExpr &AddrDelta) - : MCEncodedFragment(FT_DwarfFrame, false), AddrDelta(&AddrDelta) {} - - const MCExpr &getAddrDelta() const { return *AddrDelta; } - void setAddrDelta(const MCExpr *E) { AddrDelta = E; } - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_DwarfFrame; - } -}; - /// Represents a symbol table index fragment. class MCSymbolIdFragment : public MCFragment { const MCSymbol *Sym; diff --git a/llvm/lib/MC/MCAsmBackend.cpp b/llvm/lib/MC/MCAsmBackend.cpp index 39ef521031069..828d9cf56a71f 100644 --- a/llvm/lib/MC/MCAsmBackend.cpp +++ b/llvm/lib/MC/MCAsmBackend.cpp @@ -105,7 +105,8 @@ MCFixupKindInfo MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { return Builtins[Kind - FK_NONE]; } -bool MCAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool MCAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &, uint64_t Value, bool Resolved) const { if (!Resolved) @@ -138,9 +139,7 @@ bool MCAsmBackend::isDarwinCanonicalPersonality(const MCSymbol *Sym) const { const MCSubtargetInfo *MCAsmBackend::getSubtargetInfo(const MCFragment &F) { const MCSubtargetInfo *STI = nullptr; - if (auto *DF = dyn_cast(&F)) { - STI = DF->getSubtargetInfo(); - assert(!DF->hasInstructions() || STI != nullptr); - } + STI = F.getSubtargetInfo(); + assert(!F.hasInstructions() || STI != nullptr); return STI; } diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 480e6fe027beb..51027a4d9440b 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -203,7 +203,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const { case MCFragment::FT_CVInlineLines: case MCFragment::FT_CVDefRange: case MCFragment::FT_PseudoProbe: - return cast(F).getContents().size(); + return F.getSize(); case MCFragment::FT_Fill: { auto &FF = cast(F); int64_t NumValues = 0; @@ -285,8 +285,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const { // Compute the amount of padding required before the fragment \p F to // obey bundling restrictions, where \p FOffset is the fragment's offset in // its section and \p FSize is the fragment's size. -static uint64_t computeBundlePadding(unsigned BundleSize, - const MCEncodedFragment *F, +static uint64_t computeBundlePadding(unsigned BundleSize, const MCFragment *F, uint64_t FOffset, uint64_t FSize) { uint64_t OffsetInBundle = FOffset & (BundleSize - 1); uint64_t EndOfFragment = OffsetInBundle + FSize; @@ -322,7 +321,7 @@ static uint64_t computeBundlePadding(unsigned BundleSize, return 0; } -void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const { +void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *EF) const { // If bundling is enabled and this fragment has instructions in it, it has to // obey the bundling restrictions. With padding, we'll have: // @@ -344,9 +343,6 @@ void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const { // within-fragment padding (which would produce less padding when N is less // than the bundle size), but for now we don't. // - assert(isa(F) && - "Only MCEncodedFragment implementations have instructions"); - MCEncodedFragment *EF = cast(F); uint64_t FSize = computeFragmentSize(*EF); if (FSize > getBundleAlignSize()) @@ -358,9 +354,9 @@ void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const { report_fatal_error("Padding cannot exceed 255 bytes"); EF->setBundlePadding(static_cast(RequiredBundlePadding)); EF->Offset += RequiredBundlePadding; - if (auto *DF = dyn_cast_or_null(Prev)) - if (DF->getContents().empty()) - DF->Offset = EF->Offset; + if (Prev->getKind() == MCFragment::FT_Data) + if (Prev->getFixedSize() == 0) + Prev->Offset = EF->Offset; } // Simple getSymbolOffset helper for the non-variable case. @@ -480,8 +476,7 @@ bool MCAssembler::registerSymbol(const MCSymbol &Symbol) { return Changed; } -void MCAssembler::writeFragmentPadding(raw_ostream &OS, - const MCEncodedFragment &EF, +void MCAssembler::writeFragmentPadding(raw_ostream &OS, const MCFragment &EF, uint64_t FSize) const { assert(getBackendPtr() && "Expected assembler backend"); // Should NOP padding be written out before this fragment? @@ -523,8 +518,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, llvm::endianness Endian = Asm.getBackend().Endian; - if (const MCEncodedFragment *EF = dyn_cast(&F)) - Asm.writeFragmentPadding(OS, *EF, FragmentSize); + Asm.writeFragmentPadding(OS, F, FragmentSize); // This variable (and its dummy usage) is to participate in the assert at // the end of the function. @@ -546,8 +540,9 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, ++stats::EmittedDataFragments; else if (F.getKind() == MCFragment::FT_Relaxable) ++stats::EmittedRelaxableFragments; - const auto &EF = cast(F); + const auto &EF = cast(F); OS << StringRef(EF.getContents().data(), EF.getContents().size()); + OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size()); break; } case MCFragment::FT_Align: { @@ -717,11 +712,10 @@ void MCAssembler::writeSectionData(raw_ostream &OS, // Check that we aren't trying to write a non-zero contents (or fixups) // into a virtual section. This is to support clients which use standard // directives to fill the contents of virtual sections. - const MCDataFragment &DF = cast(F); - if (DF.getFixups().size()) + if (F.getFixups().size() || F.getVarFixups().size()) reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + Sec->getName() + "' cannot have fixups"); - for (char C : DF.getContents()) + for (char C : F.getContents()) if (C) { reportError(SMLoc(), Sec->getVirtualSectionKind() + " section '" + Sec->getName() + @@ -822,17 +816,28 @@ void MCAssembler::layout() { // Evaluate and apply the fixups, generating relocation entries as necessary. for (MCSection &Sec : *this) { - for (MCFragment &Frag : Sec) { + for (MCFragment &F : Sec) { // Process fragments with fixups here. - if (auto *F = dyn_cast(&Frag)) { - auto Contents = F->getContents(); - for (MCFixup &Fixup : F->getFixups()) { + if (F.isEncoded()) { + auto Contents = F.getContents(); + for (MCFixup &Fixup : F.getFixups()) { uint64_t FixedValue; MCValue Target; - evaluateFixup(Frag, Fixup, Target, FixedValue, + evaluateFixup(F, Fixup, Target, FixedValue, /*RecordReloc=*/true, Contents); } - } else if (auto *AF = dyn_cast(&Frag)) { + // In the variable part, fixup offsets are relative to the fixed part's + // start. Extend the variable contents to the left to account for the + // fixed part size. + Contents = MutableArrayRef(F.getParent()->ContentStorage) + .slice(F.VarContentStart - Contents.size(), F.getSize()); + for (MCFixup &Fixup : F.getVarFixups()) { + uint64_t FixedValue; + MCValue Target; + evaluateFixup(F, Fixup, Target, FixedValue, + /*RecordReloc=*/true, Contents); + } + } else if (auto *AF = dyn_cast(&F)) { // For RISC-V linker relaxation, an alignment relocation might be // needed. if (AF->hasEmitNops()) @@ -852,18 +857,18 @@ void MCAssembler::Finish() { assert(PendingErrors.empty()); } -bool MCAssembler::fixupNeedsRelaxation(const MCRelaxableFragment &F, +bool MCAssembler::fixupNeedsRelaxation(const MCFragment &F, const MCFixup &Fixup) const { assert(getBackendPtr() && "Expected assembler backend"); MCValue Target; uint64_t Value; bool Resolved = evaluateFixup(F, const_cast(Fixup), Target, Value, /*RecordReloc=*/false, {}); - return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Target, Value, + return getBackend().fixupNeedsRelaxationAdvanced(F, Fixup, Target, Value, Resolved); } -bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { +bool MCAssembler::relaxInstruction(MCFragment &F) { assert(getEmitterPtr() && "Expected CodeEmitter defined for relaxInstruction"); // If this inst doesn't ever need relaxation, ignore it. This occurs when we @@ -874,7 +879,7 @@ bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { return false; bool DoRelax = false; - for (const MCFixup &Fixup : F.getFixups()) + for (const MCFixup &Fixup : F.getVarFixups()) if ((DoRelax = fixupNeedsRelaxation(F, Fixup))) break; if (!DoRelax) @@ -882,7 +887,7 @@ bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { ++stats::RelaxedInstructions; - // TODO Refactor relaxInstruction to accept MCRelaxableFragment and remove + // TODO Refactor relaxInstruction to accept MCFragment and remove // `setInst`. MCInst Relaxed = F.getInst(); getBackend().relaxInstruction(Relaxed, *F.getSubtargetInfo()); @@ -892,30 +897,30 @@ bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) { SmallVector Data; SmallVector Fixups; getEmitter().encodeInstruction(Relaxed, Data, Fixups, *F.getSubtargetInfo()); - F.setContents(Data); - F.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); return true; } -bool MCAssembler::relaxLEB(MCLEBFragment &LF) { - const unsigned OldSize = static_cast(LF.getContents().size()); +bool MCAssembler::relaxLEB(MCFragment &F) { + const unsigned OldSize = F.getVarSize(); unsigned PadTo = OldSize; int64_t Value; - LF.clearFixups(); + F.clearVarFixups(); // Use evaluateKnownAbsolute for Mach-O as a hack: .subsections_via_symbols // requires that .uleb128 A-B is foldable where A and B reside in different // fragments. This is used by __gcc_except_table. bool Abs = getWriter().getSubsectionsViaSymbols() - ? LF.getValue().evaluateKnownAbsolute(Value, *this) - : LF.getValue().evaluateAsAbsolute(Value, *this); + ? F.getLEBValue().evaluateKnownAbsolute(Value, *this) + : F.getLEBValue().evaluateAsAbsolute(Value, *this); if (!Abs) { bool Relaxed, UseZeroPad; - std::tie(Relaxed, UseZeroPad) = getBackend().relaxLEB128(LF, Value); + std::tie(Relaxed, UseZeroPad) = getBackend().relaxLEB128(F, Value); if (!Relaxed) { - reportError(LF.getValue().getLoc(), - Twine(LF.isSigned() ? ".s" : ".u") + + reportError(F.getLEBValue().getLoc(), + Twine(F.isLEBSigned() ? ".s" : ".u") + "leb128 expression is not absolute"); - LF.setValue(MCConstantExpr::create(0, Context)); + F.setLEBValue(MCConstantExpr::create(0, Context)); } uint8_t Tmp[10]; // maximum size: ceil(64/7) PadTo = std::max(PadTo, encodeULEB128(uint64_t(Value), Tmp)); @@ -928,11 +933,11 @@ bool MCAssembler::relaxLEB(MCLEBFragment &LF) { // without either adding padding to an LEB fragment or adding extra padding // to a later alignment fragment. To accommodate such tables, relaxation can // only increase an LEB fragment size here, not decrease it. See PR35809. - if (LF.isSigned()) + if (F.isLEBSigned()) Size = encodeSLEB128(Value, Data, PadTo); else Size = encodeULEB128(Value, Data, PadTo); - LF.setContents({reinterpret_cast(Data), Size}); + F.setVarContents({reinterpret_cast(Data), Size}); return OldSize != Size; } @@ -997,48 +1002,48 @@ bool MCAssembler::relaxBoundaryAlign(MCBoundaryAlignFragment &BF) { return true; } -bool MCAssembler::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF) { +bool MCAssembler::relaxDwarfLineAddr(MCFragment &F) { bool WasRelaxed; - if (getBackend().relaxDwarfLineAddr(DF, WasRelaxed)) + if (getBackend().relaxDwarfLineAddr(F, WasRelaxed)) return WasRelaxed; MCContext &Context = getContext(); - auto OldSize = DF.getContents().size(); + auto OldSize = F.getVarSize(); int64_t AddrDelta; - bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, *this); + bool Abs = F.getAddrDelta().evaluateKnownAbsolute(AddrDelta, *this); assert(Abs && "We created a line delta with an invalid expression"); (void)Abs; int64_t LineDelta; - LineDelta = DF.getLineDelta(); + LineDelta = F.getLineDelta(); SmallVector Data; MCDwarfLineAddr::encode(Context, getDWARFLinetableParams(), LineDelta, AddrDelta, Data); - DF.setContents(Data); - DF.clearFixups(); + F.setVarContents(Data); + F.clearVarFixups(); return OldSize != Data.size(); } -bool MCAssembler::relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF) { +bool MCAssembler::relaxDwarfCallFrameFragment(MCFragment &F) { bool WasRelaxed; - if (getBackend().relaxDwarfCFA(DF, WasRelaxed)) + if (getBackend().relaxDwarfCFA(F, WasRelaxed)) return WasRelaxed; MCContext &Context = getContext(); int64_t Value; - bool Abs = DF.getAddrDelta().evaluateAsAbsolute(Value, *this); + bool Abs = F.getAddrDelta().evaluateAsAbsolute(Value, *this); if (!Abs) { - reportError(DF.getAddrDelta().getLoc(), + reportError(F.getAddrDelta().getLoc(), "invalid CFI advance_loc expression"); - DF.setAddrDelta(MCConstantExpr::create(0, Context)); + F.setAddrDelta(MCConstantExpr::create(0, Context)); return false; } - auto OldSize = DF.getContents().size(); + auto OldSize = F.getVarContents().size(); SmallVector Data; MCDwarfFrameEmitter::encodeAdvanceLoc(Context, Value, Data); - DF.setContents(Data); - DF.clearFixups(); + F.setVarContents(Data); + F.clearVarFixups(); return OldSize != Data.size(); } @@ -1085,13 +1090,13 @@ bool MCAssembler::relaxFragment(MCFragment &F) { case MCFragment::FT_Relaxable: assert(!getRelaxAll() && "Did not expect a MCRelaxableFragment in RelaxAll mode"); - return relaxInstruction(cast(F)); + return relaxInstruction(F); + case MCFragment::FT_LEB: + return relaxLEB(F); case MCFragment::FT_Dwarf: - return relaxDwarfLineAddr(cast(F)); + return relaxDwarfLineAddr(F); case MCFragment::FT_DwarfFrame: - return relaxDwarfCallFrameFragment(cast(F)); - case MCFragment::FT_LEB: - return relaxLEB(cast(F)); + return relaxDwarfCallFrameFragment(F); case MCFragment::FT_BoundaryAlign: return relaxBoundaryAlign(cast(F)); case MCFragment::FT_CVInlineLines: diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index e84b91c5c41b0..44fdaad8617f8 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -417,14 +417,14 @@ void MCELFStreamer::emitInstToData(const MCInst &Inst, // data fragment because we want all the instructions in a group to get into // the same fragment. Be careful not to do that for the first instruction in // the group, though. - MCDataFragment *DF; + MCFragment *DF; if (Assembler.isBundlingEnabled()) { MCSection &Sec = *getCurrentSectionOnly(); if (isBundleLocked() && !Sec.isBundleGroupBeforeFirstInst()) { // If we are bundle-locked, we re-use the current fragment. // The bundle-locking directive ensures this is a new data fragment. - DF = cast(getCurrentFragment()); + DF = getCurrentFragment(); CheckBundleSubtargets(DF->getSubtargetInfo(), &STI); } else { DF = getContext().allocFragment(); diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index a196591744099..bef0462e8de5c 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -352,7 +352,7 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, // the linker. bool BBeforeRelax = false, AAfterRelax = false; for (auto F = FB; F; F = F->getNext()) { - auto DF = dyn_cast(F); + auto DF = F->getKind() == MCFragment::FT_Data ? F : nullptr; if (DF && DF->isLinkerRelaxable()) { if (&*F != FB || SBOffset != DF->getContents().size()) BBeforeRelax = true; @@ -373,12 +373,12 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, unsigned Count; if (DF) { Displacement += DF->getContents().size(); - } else if (auto *RF = dyn_cast(F); - RF && Asm->hasFinalLayout()) { + } else if (F->getKind() == MCFragment::FT_Relaxable && + Asm->hasFinalLayout()) { // Before finishLayout, a relaxable fragment's size is indeterminate. // After layout, during relocation generation, it can be treated as a // data fragment. - Displacement += RF->getContents().size(); + Displacement += F->getSize(); } else if (auto *AF = dyn_cast(F); AF && Layout && AF->hasEmitNops() && !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign( diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index 5cf47e3325ff2..cd1bba8df62b9 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -24,12 +24,15 @@ using namespace llvm; -static_assert(std::is_trivially_destructible_v, +static_assert(std::is_trivially_destructible_v, "fragment classes must be trivially destructible"); MCFragment::MCFragment(FragmentType Kind, bool HasInstructions) : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false), - LinkerRelaxable(false), AllowAutoPadding(false) {} + LinkerRelaxable(false), AllowAutoPadding(false) { + static_assert(sizeof(MCFragment::Tail) <= 16, + "Keep the variable-size tail small"); +} const MCSymbol *MCFragment::getAtom() const { return cast(Parent)->getAtom(LayoutOrder); @@ -59,9 +62,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { // clang-format on } - if (const auto *EF = dyn_cast(this)) - if (auto Pad = static_cast(EF->getBundlePadding())) - OS << " BundlePadding:" << Pad; + if (auto Pad = static_cast(getBundlePadding())) + OS << " BundlePadding:" << Pad; auto printFixups = [&](llvm::ArrayRef Fixups) { if (Fixups.empty()) @@ -83,18 +85,56 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { OS << " Nops"; break; } - case MCFragment::FT_Data: { - const auto *F = cast(this); - if (F->isLinkerRelaxable()) + case MCFragment::FT_Data: + case MCFragment::FT_Relaxable: + case MCFragment::FT_LEB: + case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: { + if (isLinkerRelaxable()) OS << " LinkerRelaxable"; - auto Contents = F->getContents(); - OS << " Size:" << Contents.size() << " ["; - for (unsigned i = 0, e = Contents.size(); i != e; ++i) { + auto Fixed = getContents(); + auto Var = getVarContents(); + OS << " Size:" << Fixed.size(); + if (getKind() != MCFragment::FT_Data) + OS << '+' << Var.size(); + OS << " ["; + for (unsigned i = 0, e = Fixed.size(); i != e; ++i) { if (i) OS << ","; - OS << format("%02x", uint8_t(Contents[i])); + OS << format("%02x", uint8_t(Fixed[i])); + } + for (unsigned i = 0, e = Var.size(); i != e; ++i) { + if (Fixed.size() || i) + OS << ","; + OS << format("%02x", uint8_t(Var[i])); } OS << ']'; - printFixups(F->getFixups()); + switch (getKind()) { + case MCFragment::FT_Data: + break; + case MCFragment::FT_Relaxable: + OS << ' '; + getInst().dump_pretty(OS); + break; + case MCFragment::FT_LEB: { + OS << " Value:"; + getLEBValue().print(OS, nullptr); + OS << " Signed:" << isLEBSigned(); + break; + } + case MCFragment::FT_Dwarf: + OS << " AddrDelta:"; + getAddrDelta().print(OS, nullptr); + OS << " LineDelta:" << getLineDelta(); + break; + case MCFragment::FT_DwarfFrame: + OS << " AddrDelta:"; + getAddrDelta().print(OS, nullptr); + break; + default: + llvm_unreachable(""); + } + printFixups(getFixups()); + printFixups(getVarFixups()); break; } case MCFragment::FT_Fill: { @@ -111,13 +151,6 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { << " ControlledNopLength:" << NF->getControlledNopLength(); break; } - case MCFragment::FT_Relaxable: { - const auto *F = cast(this); - OS << " Size:" << F->getContents().size() << ' '; - F->getInst().dump_pretty(OS); - printFixups(F->getFixups()); - break; - } case MCFragment::FT_Org: { const auto *OF = cast(this); OS << " Offset:"; @@ -125,26 +158,6 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { OS << " Value:" << static_cast(OF->getValue()); break; } - case MCFragment::FT_Dwarf: { - const auto *OF = cast(this); - OS << " AddrDelta:"; - OF->getAddrDelta().print(OS, nullptr); - OS << " LineDelta:" << OF->getLineDelta(); - break; - } - case MCFragment::FT_DwarfFrame: { - const auto *CF = cast(this); - OS << " AddrDelta:"; - CF->getAddrDelta().print(OS, nullptr); - break; - } - case MCFragment::FT_LEB: { - const auto *LF = cast(this); - OS << " Value:"; - LF->getValue().print(OS, nullptr); - OS << " Signed:" << LF->isSigned(); - break; - } case MCFragment::FT_BoundaryAlign: { const auto *BF = cast(this); OS << " BoundarySize:" << BF->getAlignment().value() diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index b03c2283cdf4d..b43f109f68332 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -66,8 +66,8 @@ void MCObjectStreamer::resolvePendingFixups() { // If the location symbol to relocate is in MCEncodedFragment, // put the Fixup into location symbol's fragment. Otherwise // put into PendingFixup.DF - MCFragment *SymFragment = PendingFixup.Sym->getFragment(); - if (auto *F = dyn_cast(SymFragment)) + MCFragment *F = PendingFixup.Sym->getFragment(); + if (F->isEncoded()) F->addFixup(PendingFixup.Fixup); else PendingFixup.DF->addFixup(PendingFixup.Fixup); @@ -76,7 +76,8 @@ void MCObjectStreamer::resolvePendingFixups() { } // As a compile-time optimization, avoid allocating and evaluating an MCExpr -// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment. +// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed +// part. static std::optional absoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo) { assert(Hi && Lo); @@ -85,8 +86,11 @@ static std::optional absoluteSymbolDiff(const MCSymbol *Hi, if (Hi->isVariable() || Lo->isVariable()) return std::nullopt; auto *LoF = Lo->getFragment(); - if (!LoF || LoF->getKind() != MCFragment::FT_Data || - Hi->getFragment() != LoF || LoF->isLinkerRelaxable()) + if (!LoF || Hi->getFragment() != LoF || LoF->isLinkerRelaxable()) + return std::nullopt; + // If either symbol resides in the variable part, bail out. + auto Fixed = LoF->getFixedSize(); + if (Lo->getOffset() > Fixed || Hi->getOffset() > Fixed) return std::nullopt; return Hi->getOffset() - Lo->getOffset(); @@ -131,7 +135,7 @@ void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) { MCDwarfFrameEmitter::Emit(*this, MAB, false); } -static bool canReuseDataFragment(const MCDataFragment &F, +static bool canReuseDataFragment(const MCFragment &F, const MCAssembler &Assembler, const MCSubtargetInfo *STI) { if (!F.hasInstructions()) @@ -150,11 +154,12 @@ static bool canReuseDataFragment(const MCDataFragment &F, return !STI || F.getSubtargetInfo() == STI; } -MCDataFragment * +MCFragment * MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) { - auto *F = dyn_cast(getCurrentFragment()); - if (!F || !canReuseDataFragment(*F, *Assembler, STI)) { - F = getContext().allocFragment(); + auto *F = getCurrentFragment(); + if (F->getKind() != MCFragment::FT_Data || + !canReuseDataFragment(*F, *Assembler, STI)) { + F = getContext().allocFragment(); insert(F); } return F; @@ -256,7 +261,10 @@ void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) { emitULEB128IntValue(IntValue); return; } - insert(getContext().allocFragment(*Value, false)); + auto *F = getOrCreateDataFragment(); + F->Kind = MCFragment::FT_LEB; + F->setLEBSigned(false); + F->setLEBValue(Value); } void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) { @@ -265,7 +273,10 @@ void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) { emitSLEB128IntValue(IntValue); return; } - insert(getContext().allocFragment(*Value, true)); + auto *F = getOrCreateDataFragment(); + F->Kind = MCFragment::FT_LEB; + F->setLEBSigned(true); + F->setLEBValue(Value); } void MCObjectStreamer::emitWeakReference(MCSymbol *Alias, @@ -374,7 +385,6 @@ void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst, return; } - // Otherwise emit to a separate fragment. emitInstToFragment(Inst, STI); } @@ -396,18 +406,17 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst, void MCObjectStreamer::emitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &STI) { - // Always create a new, separate fragment here, because its size can change - // during relaxation. - MCRelaxableFragment *IF = - getContext().allocFragment(STI); - insert(IF); - IF->setInst(Inst); - + auto *F = getOrCreateDataFragment(); + SmallVector Data; SmallVector Fixups; - getAssembler().getEmitter().encodeInstruction( - Inst, IF->getContentsForAppending(), Fixups, STI); - IF->doneAppending(); - IF->appendFixups(Fixups); + getAssembler().getEmitter().encodeInstruction(Inst, Data, Fixups, STI); + + F->Kind = MCFragment::FT_Relaxable; + F->STI = &STI; + F->HasInstructions = true; + F->setVarContents(Data); + F->setVarFixups(Fixups); + F->setInst(Inst); } #ifndef NDEBUG @@ -486,9 +495,10 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, return; } - const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, SMLoc()); - insert(getContext().allocFragment(LineDelta, - *AddrDelta)); + auto *F = getOrCreateDataFragment(); + F->Kind = MCFragment::FT_Dwarf; + F->setAddrDelta(buildSymbolDiff(*this, Label, LastLabel, SMLoc())); + F->setLineDelta(LineDelta); } void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section, @@ -516,8 +526,9 @@ void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section, void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label, SMLoc Loc) { - const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, Loc); - insert(getContext().allocFragment(*AddrDelta)); + auto *F = getOrCreateDataFragment(); + F->Kind = MCFragment::FT_DwarfFrame; + F->setAddrDelta(buildSymbolDiff(*this, Label, LastLabel, Loc)); } void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo, diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index 56450033529bc..006120b0eb447 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -81,7 +81,7 @@ LLVM_DUMP_METHOD void MCSection::dump( } #endif -void MCEncodedFragment::setContents(ArrayRef Contents) { +void MCFragment::setContents(ArrayRef Contents) { auto &S = getParent()->ContentStorage; if (ContentStart + Contents.size() > ContentEnd) { ContentStart = S.size(); @@ -91,9 +91,19 @@ void MCEncodedFragment::setContents(ArrayRef Contents) { llvm::copy(Contents, S.begin() + ContentStart); } -void MCEncodedFragment::addFixup(MCFixup Fixup) { appendFixups({Fixup}); } +void MCFragment::setVarContents(ArrayRef Contents) { + auto &S = getParent()->ContentStorage; + if (VarContentStart + Contents.size() > VarContentEnd) { + VarContentStart = S.size(); + S.resize_for_overwrite(S.size() + Contents.size()); + } + VarContentEnd = VarContentStart + Contents.size(); + llvm::copy(Contents, S.begin() + VarContentStart); +} + +void MCFragment::addFixup(MCFixup Fixup) { appendFixups({Fixup}); } -void MCEncodedFragment::appendFixups(ArrayRef Fixups) { +void MCFragment::appendFixups(ArrayRef Fixups) { auto &S = getParent()->FixupStorage; if (LLVM_UNLIKELY(FixupEnd != S.size())) { // Move the elements to the end. Reserve space to avoid invalidating @@ -107,7 +117,7 @@ void MCEncodedFragment::appendFixups(ArrayRef Fixups) { FixupEnd = S.size(); } -void MCEncodedFragment::setFixups(ArrayRef Fixups) { +void MCFragment::setFixups(ArrayRef Fixups) { auto &S = getParent()->FixupStorage; if (FixupStart + Fixups.size() > FixupEnd) { FixupStart = S.size(); @@ -116,3 +126,19 @@ void MCEncodedFragment::setFixups(ArrayRef Fixups) { FixupEnd = FixupStart + Fixups.size(); llvm::copy(Fixups, S.begin() + FixupStart); } + +void MCFragment::setVarFixups(ArrayRef Fixups) { + auto &S = getParent()->FixupStorage; + if (VarFixupStart + Fixups.size() > VarFixupEnd) { + VarFixupStart = S.size(); + S.resize_for_overwrite(S.size() + Fixups.size()); + } + VarFixupEnd = VarFixupStart + Fixups.size(); + // Source fixup offsets are relative to the variable part's start. Add the + // fixed part size to make them relative to the fixed part's start. + std::transform(Fixups.begin(), Fixups.end(), S.begin() + VarFixupStart, + [Fixed = getFixedSize()](MCFixup F) { + F.setOffset(Fixed + F.getOffset()); + return F; + }); +} diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index d148b521ff9fe..5c4a355f59fc4 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -711,10 +711,8 @@ static void addData(SmallVectorImpl &DataBytes, llvm_unreachable("The fill should be an assembler constant"); DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues, Fill->getValue()); - } else if (auto *LEB = dyn_cast(&Frag)) { - llvm::append_range(DataBytes, LEB->getContents()); } else { - llvm::append_range(DataBytes, cast(Frag).getContents()); + llvm::append_range(DataBytes, Frag.getContents()); } } @@ -1884,7 +1882,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority)) report_fatal_error("invalid .init_array section priority"); } - const auto &DataFrag = cast(Frag); + const auto &DataFrag = Frag; assert(llvm::all_of(DataFrag.getContents(), [](char C) { return !C; })); for (const MCFixup &Fixup : DataFrag.getFixups()) { assert(Fixup.getKind() == diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp index f2144375fd95e..233f42b7a4790 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -529,11 +529,9 @@ void AArch64TargetELFStreamer::finish() { static_cast(Ctx.getObjectFileInfo()->getTextSection()); bool Empty = true; for (auto &F : *Text) { - if (auto *DF = dyn_cast(&F)) { - if (!DF->getContents().empty()) { - Empty = false; - break; - } + if (F.getSize()) { + Empty = false; + break; } } if (Empty) diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 376bddb120d5f..980031355bf43 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -311,7 +311,8 @@ static bool needsInterworking(const MCAssembler &Asm, const MCSymbol *Sym, return false; } -bool ARMAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool ARMAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &Target, uint64_t Value, bool Resolved) const { diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h index 877e3afdb1d57..07d2cf784c442 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h @@ -51,7 +51,8 @@ class ARMAsmBackend : public MCAsmBackend { const char *reasonForFixupRelaxation(const MCFixup &Fixup, uint64_t Value) const; - bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, uint64_t, + bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, bool) const override; void relaxInstruction(MCInst &Inst, diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index c61e405bd3a02..910806e99836a 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -650,11 +650,11 @@ class ARMELFStreamer : public MCELFStreamer { // This is a tentative symbol, it won't really be emitted until it's // actually needed. ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); - auto *DF = dyn_cast_or_null(getCurrentFragment()); - if (!DF) + auto *DF = getCurrentFragment(); + if (DF->getKind() != MCFragment::FT_Data) return; EMS->F = DF; - EMS->Offset = DF->getContents().size(); + EMS->Offset = DF->getFixedSize(); LastEMSInfo->State = EMS_Data; return; } @@ -1145,9 +1145,8 @@ void ARMTargetELFStreamer::finish() { auto *Text = static_cast(Ctx.getObjectFileInfo()->getTextSection()); for (auto &F : *Text) - if (auto *DF = dyn_cast(&F)) - if (!DF->getContents().empty()) - return; + if (F.getSize()) + return; Text->setFlags(Text->getFlags() | ELF::SHF_ARM_PURECODE); } } diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp index ce1da6e58b9cd..5b5112881fd3d 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp @@ -157,7 +157,8 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, } } -bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &, uint64_t Value, bool Resolved) const { diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h index 1d3a22c2bbbb4..1c8516fbf53a7 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.h @@ -38,7 +38,8 @@ class CSKYAsmBackend : public MCAsmBackend { void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, uint64_t, + bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, bool) const override; bool writeNopData(raw_ostream &OS, uint64_t Count, diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp index de7bd5d4b2c66..2bb8069062ba5 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -46,16 +46,15 @@ class HexagonAsmBackend : public MCAsmBackend { MCInst * Extender; unsigned MaxPacketSize; - void ReplaceInstruction(MCCodeEmitter &E, MCRelaxableFragment &RF, - MCInst &HMB) const { + void ReplaceInstruction(MCCodeEmitter &E, MCFragment &RF, MCInst &HMB) const { SmallVector Fixups; SmallString<256> Code; E.encodeInstruction(HMB, Code, Fixups, *RF.getSubtargetInfo()); // Update the fragment. RF.setInst(HMB); - RF.setContents(Code); - RF.getFixups() = Fixups; + RF.setVarContents(Code); + RF.setVarFixups(Fixups); } public: @@ -438,15 +437,15 @@ class HexagonAsmBackend : public MCAsmBackend { /// fixupNeedsRelaxation - Target specific predicate for whether a given /// fixup requires the associated instruction to be relaxed. - bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, const MCValue &, - uint64_t Value, + bool fixupNeedsRelaxationAdvanced(const MCFragment &F, const MCFixup &Fixup, + const MCValue &, uint64_t Value, bool Resolved) const override { MCInst const &MCB = RelaxedMCB; assert(HexagonMCInstrInfo::isBundle(MCB)); *RelaxTarget = nullptr; MCInst &MCI = const_cast(HexagonMCInstrInfo::instruction( - MCB, Fixup.getOffset() / HEXAGON_INSTR_SIZE)); + MCB, (Fixup.getOffset() - F.getFixedSize()) / HEXAGON_INSTR_SIZE)); bool Relaxable = isInstRelaxable(MCI); if (Relaxable == false) return false; @@ -595,7 +594,7 @@ class HexagonAsmBackend : public MCAsmBackend { } case MCFragment::FT_Relaxable: { MCContext &Context = getContext(); - auto &RF = cast(*Frags[K]); + auto &RF = *Frags[K]; MCInst Inst = RF.getInst(); const bool WouldTraverseLabel = llvm::any_of( diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp index 1b8893029bb33..3df5f1e619168 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp @@ -279,23 +279,23 @@ getRelocPairForSize(unsigned Size) { } } -std::pair LoongArchAsmBackend::relaxLEB128(MCLEBFragment &LF, +std::pair LoongArchAsmBackend::relaxLEB128(MCFragment &LF, int64_t &Value) const { - const MCExpr &Expr = LF.getValue(); - if (LF.isSigned() || !Expr.evaluateKnownAbsolute(Value, *Asm)) + const MCExpr &Expr = LF.getLEBValue(); + if (LF.isLEBSigned() || !Expr.evaluateKnownAbsolute(Value, *Asm)) return std::make_pair(false, false); - LF.addFixup(MCFixup::create(0, &Expr, FK_Data_leb128)); + LF.setVarFixups({MCFixup::create(0, &Expr, FK_Data_leb128)}); return std::make_pair(true, true); } -bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, +bool LoongArchAsmBackend::relaxDwarfLineAddr(MCFragment &DF, bool &WasRelaxed) const { MCContext &C = getContext(); int64_t LineDelta = DF.getLineDelta(); const MCExpr &AddrDelta = DF.getAddrDelta(); SmallVector Fixups; - size_t OldSize = DF.getContents().size(); + size_t OldSize = DF.getVarSize(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -349,17 +349,16 @@ bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, OS << uint8_t(dwarf::DW_LNS_copy); } - DF.setContents(Data); - DF.setFixups(Fixups); + DF.setVarContents(Data); + DF.setVarFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; } -bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const { - const MCExpr &AddrDelta = DF.getAddrDelta(); +bool LoongArchAsmBackend::relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const { + const MCExpr &AddrDelta = F.getAddrDelta(); SmallVector Fixups; - size_t OldSize = DF.getContents().size(); + size_t OldSize = F.getVarContents().size(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -371,9 +370,9 @@ bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, assert(getContext().getAsmInfo()->getMinInstAlignment() == 1 && "expected 1-byte alignment"); if (Value == 0) { - DF.clearContents(); - DF.clearFixups(); - WasRelaxed = OldSize != DF.getContents().size(); + F.clearVarContents(); + F.clearVarFixups(); + WasRelaxed = OldSize != 0; return true; } @@ -405,8 +404,8 @@ bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, } else { llvm_unreachable("unsupported CFA encoding"); } - DF.setContents(Data); - DF.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h index 4446cadf11e22..b32ba067810ce 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h @@ -59,11 +59,9 @@ class LoongArchAsmBackend : public MCAsmBackend { MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override; - bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, - bool &WasRelaxed) const override; - bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const override; - std::pair relaxLEB128(MCLEBFragment &LF, + bool relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const override; + bool relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const override; + std::pair relaxLEB128(MCFragment &F, int64_t &Value) const override; bool writeNopData(raw_ostream &OS, uint64_t Count, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index 89a87798d71e4..48bc4c1f03166 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -103,7 +103,8 @@ MCFixupKindInfo RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { return Infos[Kind - FirstTargetFixupKind]; } -bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &, uint64_t Value, bool Resolved) const { @@ -267,14 +268,14 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst, Inst = std::move(Res); } -bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, +bool RISCVAsmBackend::relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const { MCContext &C = getContext(); - int64_t LineDelta = DF.getLineDelta(); - const MCExpr &AddrDelta = DF.getAddrDelta(); + int64_t LineDelta = F.getLineDelta(); + const MCExpr &AddrDelta = F.getAddrDelta(); SmallVector Fixups; - size_t OldSize = DF.getContents().size(); + size_t OldSize = F.getVarSize(); int64_t Value; [[maybe_unused]] bool IsAbsolute = @@ -327,17 +328,16 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, OS << uint8_t(dwarf::DW_LNS_copy); } - DF.setContents(Data); - DF.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; } -bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const { - const MCExpr &AddrDelta = DF.getAddrDelta(); +bool RISCVAsmBackend::relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const { + const MCExpr &AddrDelta = F.getAddrDelta(); SmallVector Fixups; - size_t OldSize = DF.getContents().size(); + size_t OldSize = F.getVarSize(); int64_t Value; if (AddrDelta.evaluateAsAbsolute(Value, *Asm)) @@ -349,9 +349,9 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, assert(getContext().getAsmInfo()->getMinInstAlignment() == 1 && "expected 1-byte alignment"); if (Value == 0) { - DF.clearContents(); - DF.clearFixups(); - WasRelaxed = OldSize != DF.getContents().size(); + F.clearVarContents(); + F.clearVarFixups(); + WasRelaxed = OldSize != 0; return true; } @@ -382,20 +382,20 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF, } else { llvm_unreachable("unsupported CFA encoding"); } - DF.setContents(Data); - DF.setFixups(Fixups); + F.setVarContents(Data); + F.setVarFixups(Fixups); WasRelaxed = OldSize != Data.size(); return true; } -std::pair RISCVAsmBackend::relaxLEB128(MCLEBFragment &LF, +std::pair RISCVAsmBackend::relaxLEB128(MCFragment &LF, int64_t &Value) const { - if (LF.isSigned()) + if (LF.isLEBSigned()) return std::make_pair(false, false); - const MCExpr &Expr = LF.getValue(); + const MCExpr &Expr = LF.getLEBValue(); if (ULEB128Reloc) { - LF.addFixup(MCFixup::create(0, &Expr, FK_Data_leb128)); + LF.setVarFixups({MCFixup::create(0, &Expr, FK_Data_leb128)}); } return std::make_pair(Expr.evaluateKnownAbsolute(Value, *Asm), false); } @@ -620,14 +620,13 @@ static const MCFixup *getPCRelHiFixup(const MCSpecifierExpr &Expr, const MCSymbol *AUIPCSymbol = AUIPCLoc.getAddSym(); if (!AUIPCSymbol) return nullptr; - const auto *DF = dyn_cast_or_null(AUIPCSymbol->getFragment()); - + const auto *DF = AUIPCSymbol->getFragment(); if (!DF) return nullptr; uint64_t Offset = AUIPCSymbol->getOffset(); if (DF->getContents().size() == Offset) { - DF = dyn_cast_or_null(DF->getNext()); + DF = DF->getNext(); if (!DF) return nullptr; Offset = 0; diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h index 1f1a6f5fe31a0..8c10fbec3c8fc 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -60,7 +60,8 @@ class RISCVAsmBackend : public MCAsmBackend { std::unique_ptr createObjectTargetWriter() const override; - bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, uint64_t, + bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, bool) const override; std::optional getFixupKind(StringRef Name) const override; @@ -72,11 +73,9 @@ class RISCVAsmBackend : public MCAsmBackend { void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, - bool &WasRelaxed) const override; - bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, - bool &WasRelaxed) const override; - std::pair relaxLEB128(MCLEBFragment &LF, + bool relaxDwarfLineAddr(MCFragment &F, bool &WasRelaxed) const override; + bool relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const override; + std::pair relaxLEB128(MCFragment &LF, int64_t &Value) const override; bool writeNopData(raw_ostream &OS, uint64_t Count, diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index ff2df3d5b192a..9023fc40d4ed8 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -26,6 +26,7 @@ #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/TargetRegistry.h" @@ -177,20 +178,20 @@ class X86AsmBackend : public MCAsmBackend { bool mayNeedRelaxation(unsigned Opcode, ArrayRef Operands, const MCSubtargetInfo &STI) const override; - bool fixupNeedsRelaxationAdvanced(const MCFixup &, const MCValue &, uint64_t, + bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, + const MCValue &, uint64_t, bool) const override; void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override; - bool padInstructionViaRelaxation(MCRelaxableFragment &RF, - MCCodeEmitter &Emitter, + bool padInstructionViaRelaxation(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const; - bool padInstructionViaPrefix(MCRelaxableFragment &RF, MCCodeEmitter &Emitter, + bool padInstructionViaPrefix(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const; - bool padInstructionEncoding(MCRelaxableFragment &RF, MCCodeEmitter &Emitter, + bool padInstructionEncoding(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const; bool finishLayout(const MCAssembler &Asm) const override; @@ -409,10 +410,9 @@ isRightAfterData(MCFragment *CurrentFragment, // it, returns true. // - Otherwise returns false. // - If the fragment is not a DataFragment, returns false. - if (auto *DF = dyn_cast_or_null(F)) - return DF->getContents().size() && - (DF != PrevInstPosition.first || - DF->getContents().size() != PrevInstPosition.second); + if (F->getKind() == MCFragment::FT_Data) + return F->getFixedSize() && (F != PrevInstPosition.first || + F->getFixedSize() != PrevInstPosition.second); return false; } @@ -421,11 +421,7 @@ isRightAfterData(MCFragment *CurrentFragment, static size_t getSizeForInstFragment(const MCFragment *F) { if (!F || !F->hasInstructions()) return 0; - // MCEncodedFragmentWithContents being templated makes this tricky. - if (auto *DF = dyn_cast(F)) - return DF->getContents().size(); - else - llvm_unreachable("Unknown fragment with instructions!"); + return F->getSize(); } /// Return true if we can insert NOP or prefixes automatically before the @@ -551,8 +547,8 @@ void X86AsmBackend::emitInstructionBegin(MCObjectStreamer &OS, void X86AsmBackend::emitInstructionEnd(MCObjectStreamer &OS, const MCInst &Inst) { MCFragment *CF = OS.getCurrentFragment(); - if (auto *F = dyn_cast_or_null(CF)) - F->setAllowAutoPadding(canPadInst(Inst, OS)); + if (CF->getKind() == MCFragment::FT_Relaxable) + CF->setAllowAutoPadding(canPadInst(Inst, OS)); // Update PrevInstOpcode here, canPadInst() reads that. PrevInstOpcode = Inst.getOpcode(); @@ -756,7 +752,8 @@ bool X86AsmBackend::mayNeedRelaxation(unsigned Opcode, Operands[Operands.size() - 1 - SkipOperands].isExpr()); } -bool X86AsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, +bool X86AsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &, + const MCFixup &Fixup, const MCValue &Target, uint64_t Value, bool Resolved) const { @@ -785,7 +782,7 @@ void X86AsmBackend::relaxInstruction(MCInst &Inst, Inst.setOpcode(RelaxedOp); } -bool X86AsmBackend::padInstructionViaPrefix(MCRelaxableFragment &RF, +bool X86AsmBackend::padInstructionViaPrefix(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const { if (!RF.getAllowAutoPadding()) @@ -798,7 +795,7 @@ bool X86AsmBackend::padInstructionViaPrefix(MCRelaxableFragment &RF, *RF.getSubtargetInfo())) return false; - const unsigned OldSize = RF.getContents().size(); + const unsigned OldSize = RF.getVarContents().size(); if (OldSize == 15) return false; @@ -827,19 +824,18 @@ bool X86AsmBackend::padInstructionViaPrefix(MCRelaxableFragment &RF, SmallString<256> Code; Code.append(PrefixBytesToAdd, Prefix); - Code.append(RF.getContents().begin(), RF.getContents().end()); - RF.setContents(Code); + Code.append(RF.getVarContents().begin(), RF.getVarContents().end()); + RF.setVarContents(Code); // Adjust the fixups for the change in offsets - for (auto &F : RF.getFixups()) { - F.setOffset(F.getOffset() + PrefixBytesToAdd); - } + for (auto &F : RF.getVarFixups()) + F.setOffset(PrefixBytesToAdd + F.getOffset()); RemainingSize -= PrefixBytesToAdd; return true; } -bool X86AsmBackend::padInstructionViaRelaxation(MCRelaxableFragment &RF, +bool X86AsmBackend::padInstructionViaRelaxation(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const { if (!mayNeedRelaxation(RF.getOpcode(), RF.getOperands(), @@ -854,20 +850,20 @@ bool X86AsmBackend::padInstructionViaRelaxation(MCRelaxableFragment &RF, SmallVector Fixups; SmallString<15> Code; Emitter.encodeInstruction(Relaxed, Code, Fixups, *RF.getSubtargetInfo()); - const unsigned OldSize = RF.getContents().size(); + const unsigned OldSize = RF.getVarContents().size(); const unsigned NewSize = Code.size(); assert(NewSize >= OldSize && "size decrease during relaxation?"); unsigned Delta = NewSize - OldSize; if (Delta > RemainingSize) return false; RF.setInst(Relaxed); - RF.setContents(Code); - RF.setFixups(Fixups); + RF.setVarContents(Code); + RF.setVarFixups(Fixups); RemainingSize -= Delta; return true; } -bool X86AsmBackend::padInstructionEncoding(MCRelaxableFragment &RF, +bool X86AsmBackend::padInstructionEncoding(MCFragment &RF, MCCodeEmitter &Emitter, unsigned &RemainingSize) const { bool Changed = false; @@ -900,7 +896,7 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const { if (!Sec.isText()) continue; - SmallVector Relaxable; + SmallVector Relaxable; for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) { MCFragment &F = *I; @@ -911,7 +907,7 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const { continue; if (F.getKind() == MCFragment::FT_Relaxable) { - auto &RF = cast(*I); + auto &RF = cast(*I); Relaxable.push_back(&RF); continue; } diff --git a/llvm/test/MC/ELF/mc-dump.s b/llvm/test/MC/ELF/mc-dump.s index 36d3a05768dc6..ee035ef5b0e35 100644 --- a/llvm/test/MC/ELF/mc-dump.s +++ b/llvm/test/MC/ELF/mc-dump.s @@ -11,40 +11,46 @@ # CHECK-NEXT:0 Align Align:4 Value:0 ValueSize:1 MaxBytesToEmit:4 Nops # CHECK-NEXT:0 Data Size:0 [] # CHECK-NEXT: Symbol @0 _start +# CHECK-NEXT: Symbol @0 Temporary # CHECK-NEXT:0 Org Offset:3 Value:0 -# CHECK-NEXT:3 Relaxable Size:2 > +# CHECK-NEXT:3 Relaxable Size:0+2 [eb,00] > # CHECK-NEXT: Fixup @1 Value:.Ltmp0 Kind:4001 # CHECK-NEXT:5 Data Size:16 [48,8b,04,25,00,00,00,00,48,8b,04,25,00,00,00,00] # CHECK-NEXT: Fixup @4 Value:f0@ Kind:4017 # CHECK-NEXT: Fixup @12 Value:_start@ Kind:4017 # CHECK-NEXT: Symbol @16 .Ltmp0 Temporary +# CHECK-NEXT: Symbol @0 Temporary +# CHECK-NEXT: Symbol @16 Temporary # CHECK-NEXT:MCSection Name:.data # CHECK-NEXT:0 Data Size:0 [] # CHECK-NEXT: Symbol @0 .data # CHECK-NEXT:0 Align Align:4 Value:0 ValueSize:1 MaxBytesToEmit:4 # CHECK-NEXT:0 Data Size:4 [01,00,00,00] # CHECK-NEXT:4 Fill Value:0 ValueSize:1 NumValues:1 -# CHECK-NEXT:5 LEB Value:.Ltmp0-_start Signed:0 -# CHECK-NEXT:] +# CHECK-NEXT:5 LEB Size:0+1 [15] Value:.Ltmp0-_start Signed:0 +# CHECK:] # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t -debug-only=mc-dump -save-temp-labels -g 2>&1 | FileCheck %s --check-prefix=CHECK2 # CHECK2:5 Data Size:16 [48,8b,04,25,00,00,00,00,48,8b,04,25,00,00,00,00] # CHECK2-NEXT: Fixup @4 Value:f0@ Kind:4017 # CHECK2-NEXT: Fixup @12 Value:_start@ Kind:4017 -# CHECK2-NEXT: Symbol @16 .Ltmp1 -# CHECK2-NEXT: Symbol @0 .Ltmp3 Temporary -# CHECK2-NEXT: Symbol @8 .Ltmp4 Temporary -# CHECK2-NEXT: Symbol @16 .Ltmp5 Temporary -# CHECK2-NEXT: Symbol @16 .Lsec_end0 Temporary +# CHECK2-NEXT: Symbol @16 .Ltmp2 +# CHECK2-NEXT: Symbol @0 .Lcfi0 Temporary +# CHECK2:MCSection Name:.eh_frame +# CHECK2:24 DwarfCallFrame Size:17+1 [00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,45] AddrDelta:.Lcfi0-.Ltmp1 +# CHECK2-NEXT: Fixup @0 Value:.Ltmp12-.Ltmp11-0 Kind:4003 _start: var = _start +.cfi_startproc .org 3 jmp 1f +.cfi_offset %rbp, -24 movq f0@GOTPCREL, %rax movq _start@GOTPCREL, %rax 1: +.cfi_endproc .data .p2align 2