diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
commit | 5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch) | |
tree | a6140557876943cdd800ee997c9317283394b22c /include/llvm/MC | |
parent | f03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff) |
Notes
Diffstat (limited to 'include/llvm/MC')
51 files changed, 1908 insertions, 2070 deletions
diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h index 1fc0332f63c29..9aa4663ba0fc9 100644 --- a/include/llvm/MC/ConstantPools.h +++ b/include/llvm/MC/ConstantPools.h @@ -73,21 +73,18 @@ class AssemblerConstantPools { // sections in a stable order to ensure that we have print the // constant pools in a deterministic order when printing an assembly // file. - typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy; + typedef MapVector<MCSection *, ConstantPool> ConstantPoolMapTy; ConstantPoolMapTy ConstantPools; public: - AssemblerConstantPools() {} - ~AssemblerConstantPools() {} - void emitAll(MCStreamer &Streamer); void emitForCurrentSection(MCStreamer &Streamer); const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr, unsigned Size); private: - ConstantPool *getConstantPool(const MCSection *Section); - ConstantPool &getOrCreateConstantPool(const MCSection *Section); + ConstantPool *getConstantPool(MCSection *Section); + ConstantPool &getOrCreateConstantPool(MCSection *Section); }; } // end namespace llvm diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index a6d41392724e0..c0a95d48e370e 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -30,10 +30,10 @@ class MCSection; class MCValue; class raw_ostream; -/// MCAsmBackend - Generic interface to target specific assembler backends. +/// Generic interface to target specific assembler backends. class MCAsmBackend { - MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION; + MCAsmBackend(const MCAsmBackend &) = delete; + void operator=(const MCAsmBackend &) = delete; protected: // Can only create subclasses. MCAsmBackend(); @@ -46,70 +46,62 @@ public: /// lifetime management virtual void reset() {} - /// createObjectWriter - Create a new MCObjectWriter instance for use by the - /// assembler backend to emit the final object file. - virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0; + /// Create a new MCObjectWriter instance for use by the assembler backend to + /// emit the final object file. + virtual MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const = 0; - /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable - /// non-standard ELFObjectWriters. + /// Create a new ELFObjectTargetWriter to enable non-standard + /// ELFObjectWriters. virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { llvm_unreachable("createELFObjectTargetWriter is not supported by asm " "backend"); } - /// hasDataInCodeSupport - Check whether this target implements data-in-code - /// markers. If not, data region directives will be ignored. + /// Check whether this target implements data-in-code markers. If not, data + /// region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } - /// doesSectionRequireSymbols - Check whether the given section requires that - /// all symbols (even temporaries) have symbol table entries. - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { - return false; - } - - /// @name Target Fixup Interfaces + /// \name Target Fixup Interfaces /// @{ - /// getNumFixupKinds - Get the number of target specific fixup kinds. + /// Get the number of target specific fixup kinds. virtual unsigned getNumFixupKinds() const = 0; - /// getFixupKindInfo - Get information on a fixup kind. + /// Get information on a fixup kind. virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; - /// processFixupValue - Target hook to adjust the literal value of a fixup - /// if necessary. IsResolved signals whether the caller believes a relocation - /// is needed; the target can modify the value. The default does nothing. + /// Target hook to adjust the literal value of a fixup if necessary. + /// IsResolved signals whether the caller believes a relocation is needed; the + /// target can modify the value. The default does nothing. virtual void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, const MCValue &Target, uint64_t &Value, bool &IsResolved) {} - /// applyFixup - Apply the \p Value for given \p Fixup into the provided - /// data fragment, at the offset specified by the fixup and following the - /// fixup kind as appropriate. + /// Apply the \p Value for given \p Fixup into the provided data fragment, at + /// the offset specified by the fixup and following the fixup kind as + /// appropriate. virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value, bool IsPCRel) const = 0; /// @} - /// @name Target Relaxation Interfaces + /// \name Target Relaxation Interfaces /// @{ - /// mayNeedRelaxation - Check whether the given instruction may need - /// relaxation. + /// Check whether the given instruction may need relaxation. /// /// \param Inst - The instruction to test. virtual bool mayNeedRelaxation(const MCInst &Inst) const = 0; - /// fixupNeedsRelaxation - Target specific predicate for whether a given - /// fixup requires the associated instruction to be relaxed. + /// Target specific predicate for whether a given fixup requires the + /// associated instruction to be relaxed. virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; - /// RelaxInstruction - Relax the instruction in the given fragment to the next - /// wider instruction. + /// Relax the instruction in the given fragment to the next wider instruction. /// /// \param Inst The instruction to relax, which may be the same as the /// output. @@ -118,22 +110,19 @@ public: /// @} - /// getMinimumNopSize - Returns the minimum size of a nop in bytes on this - /// target. The assembler will use this to emit excess padding in situations - /// where the padding required for simple alignment would be less than the - /// minimum nop size. + /// Returns the minimum size of a nop in bytes on this target. The assembler + /// will use this to emit excess padding in situations where the padding + /// required for simple alignment would be less than the minimum nop size. /// virtual unsigned getMinimumNopSize() const { return 1; } - /// writeNopData - Write an (optimal) nop sequence of Count bytes to the given - /// output. If the target cannot generate such a sequence, it should return an - /// error. + /// Write an (optimal) nop sequence of Count bytes to the given output. If the + /// target cannot generate such a sequence, it should return an error. /// /// \return - True on success. virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW) const = 0; - /// handleAssemblerFlag - Handle any target-specific assembler flags. - /// By default, do nothing. + /// Handle any target-specific assembler flags. By default, do nothing. virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} /// \brief Generate the compact unwind encoding for the CFI instructions. diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index a750a0fd5cefd..0335f3188fc35 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -18,7 +18,6 @@ #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MachineLocation.h" #include <cassert> #include <vector> @@ -37,17 +36,17 @@ enum class EncodingType { ARM, /// Windows NT (Windows on ARM) CE, /// Windows CE ARM, PowerPC, SH3, SH4 Itanium, /// Windows x64, Windows Itanium (IA-64) + X86, /// Windows x86, uses no CFI, just EH tables MIPS = Alpha, }; } enum class ExceptionHandling { - None, /// No exception support - DwarfCFI, /// DWARF-like instruction based exceptions - SjLj, /// setjmp/longjmp based exceptions - ARM, /// ARM EHABI - ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata) - MSVC, /// MSVC compatible exception handling + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + WinEH, /// Windows Exception Handling }; namespace LCOMM { @@ -119,6 +118,9 @@ protected: // Print the EH begin symbol with an assignment. Defaults to false. bool UseAssignmentForEHBegin; + // Do we need to create a local symbol for .size? + bool NeedsLocalForSize; + /// This prefix is used for globals like constant pool entries that are /// completely private to the .s file and should not have names in the .o /// file. Defaults to "L" @@ -226,7 +228,7 @@ protected: /// True if the expression /// .long f - g - /// uses an relocation but it can be supressed by writting + /// uses a relocation but it can be suppressed by writing /// a = f - g /// .long a bool SetDirectiveSuppressesReloc; @@ -254,6 +256,10 @@ protected: /// argument and how it is interpreted. Defaults to NoAlignment. LCOMM::LCOMMType LCOMMDirectiveAlignmentType; + // True if the target allows .align directives on functions. This is true for + // most targets, so defaults to true. + bool HasFunctionAlignment; + /// True if the target has .type and .size directives, this is true for most /// ELF targets. Defaults to true. bool HasDotTypeDotSizeDirective; @@ -333,7 +339,7 @@ protected: std::vector<MCCFIInstruction> InitialFrameState; - //===--- Integrated Assembler State ----------------------------------===// + //===--- Integrated Assembler Information ----------------------------===// /// Should we use the integrated assembler? /// The integrated assembler should be enabled by default (by the @@ -345,6 +351,10 @@ protected: /// Compress DWARF debug sections. Defaults to false. bool CompressDebugSections; + /// True if the integrated assembler should interpret 'a >> b' constant + /// expressions as logical rather than arithmetic. + bool UseLogicalShr; + public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); @@ -378,7 +388,7 @@ public: /// Targets can implement this method to specify a section to switch to if the /// translation unit doesn't have any trampolines that require an executable /// stack. - virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const { + virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const { return nullptr; } @@ -428,6 +438,7 @@ public: const char *getLabelSuffix() const { return LabelSuffix; } bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } + bool needsLocalForSize() const { return NeedsLocalForSize; } const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } const char *getPrivateLabelPrefix() const { return PrivateLabelPrefix; } bool hasLinkerPrivateGlobalPrefix() const { @@ -464,6 +475,7 @@ public: LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const { return LCOMMDirectiveAlignmentType; } + bool hasFunctionAlignment() const { return HasFunctionAlignment; } bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; } bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasIdentDirective() const { return HasIdentDirective; } @@ -490,18 +502,17 @@ public: ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } - /// Return true if the exception handling type uses the language-specific data - /// area (LSDA) format specified by the Itanium C++ ABI. - bool usesItaniumLSDAForExceptions() const { + /// Returns true if the exception handling method for the platform uses call + /// frame information to unwind. + bool usesCFIForEH() const { return (ExceptionsType == ExceptionHandling::DwarfCFI || - ExceptionsType == ExceptionHandling::ARM || - // This Windows EH type uses the Itanium LSDA encoding. - ExceptionsType == ExceptionHandling::ItaniumWinEH); + ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI()); } bool usesWindowsCFI() const { - return ExceptionsType == ExceptionHandling::ItaniumWinEH || - ExceptionsType == ExceptionHandling::MSVC; + return ExceptionsType == ExceptionHandling::WinEH && + (WinEHEncodingType != WinEH::EncodingType::Invalid && + WinEHEncodingType != WinEH::EncodingType::X86); } bool doesDwarfUseRelocationsAcrossSections() const { @@ -532,6 +543,8 @@ public: void setCompressDebugSections(bool CompressDebugSections) { this->CompressDebugSections = CompressDebugSections; } + + bool shouldUseLogicalShr() const { return UseLogicalShr; } }; } diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h index 7bd246056eca0..7125f5c7ad7a7 100644 --- a/include/llvm/MC/MCAsmInfoELF.h +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -15,8 +15,7 @@ namespace llvm { class MCAsmInfoELF : public MCAsmInfo { virtual void anchor(); - const MCSection * - getNonexecutableStackSection(MCContext &Ctx) const override final; + MCSection *getNonexecutableStackSection(MCContext &Ctx) const final; protected: MCAsmInfoELF(); diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index f048e34671db4..fb28420e0fa3a 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -16,7 +16,7 @@ namespace llvm { class MCAssembler; class MCFragment; -class MCSectionData; +class MCSection; class MCSymbol; class MCSymbolData; @@ -28,20 +28,15 @@ class MCSymbolData; /// efficiently compute the exact address of any symbol in the assembly file, /// even during the relaxation process. class MCAsmLayout { -public: - typedef llvm::SmallVectorImpl<MCSectionData*>::const_iterator const_iterator; - typedef llvm::SmallVectorImpl<MCSectionData*>::iterator iterator; - -private: MCAssembler &Assembler; /// List of sections in layout order. - llvm::SmallVector<MCSectionData*, 16> SectionOrder; + llvm::SmallVector<MCSection *, 16> SectionOrder; /// The last fragment which was laid out, or 0 if nothing has been laid /// out. Fragments are always laid out in order, so all fragments with a /// lower ordinal will be valid. - mutable DenseMap<const MCSectionData*, MCFragment*> LastValidFragment; + mutable DenseMap<const MCSection *, MCFragment *> LastValidFragment; /// \brief Make sure that the layout for the given fragment is valid, lazily /// computing it if necessary. @@ -50,13 +45,8 @@ private: /// \brief Is the layout for this fragment valid? bool isFragmentValid(const MCFragment *F) const; - /// \brief Compute the amount of padding required before this fragment to - /// obey bundling restrictions. - uint64_t computeBundlePadding(const MCFragment *F, - uint64_t FOffset, uint64_t FSize); - public: - MCAsmLayout(MCAssembler &_Assembler); + MCAsmLayout(MCAssembler &Assembler); /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } @@ -71,43 +61,41 @@ public: /// been initialized. void layoutFragment(MCFragment *Fragment); - /// @name Section Access (in layout order) + /// \name Section Access (in layout order) /// @{ - llvm::SmallVectorImpl<MCSectionData*> &getSectionOrder() { - return SectionOrder; - } - const llvm::SmallVectorImpl<MCSectionData*> &getSectionOrder() const { + llvm::SmallVectorImpl<MCSection *> &getSectionOrder() { return SectionOrder; } + const llvm::SmallVectorImpl<MCSection *> &getSectionOrder() const { return SectionOrder; } /// @} - /// @name Fragment Layout Data + /// \name Fragment Layout Data /// @{ /// \brief Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; /// @} - /// @name Utility Functions + /// \name Utility Functions /// @{ /// \brief Get the address space size of the given section, as it effects /// layout. This may differ from the size reported by \see getSectionSize() by /// not including section tail padding. - uint64_t getSectionAddressSize(const MCSectionData *SD) const; + uint64_t getSectionAddressSize(const MCSection *Sec) const; /// \brief Get the data size of the given section, as emitted to the object /// file. This may include additional padding, or be 0 for virtual sections. - uint64_t getSectionFileSize(const MCSectionData *SD) const; + uint64_t getSectionFileSize(const MCSection *Sec) const; /// \brief Get the offset of the given symbol, as computed in the current /// layout. - /// \result True on success. - bool getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const; + /// \return True on success. + bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const; /// \brief Variant that reports a fatal error if the offset is not computable. - uint64_t getSymbolOffset(const MCSymbolData *SD) const; + uint64_t getSymbolOffset(const MCSymbol &S) const; /// \brief If this symbol is equivalent to A + Constant, return A. const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 681a317287992..593504ce06079 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -11,16 +11,20 @@ #define LLVM_MC_MCASSEMBLER_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" #include <algorithm> @@ -36,18 +40,15 @@ class MCExpr; class MCFragment; class MCObjectWriter; class MCSection; -class MCSectionData; class MCSubtargetInfo; -class MCSymbol; -class MCSymbolData; class MCValue; class MCAsmBackend; class MCFragment : public ilist_node<MCFragment> { friend class MCAsmLayout; - MCFragment(const MCFragment&) LLVM_DELETED_FUNCTION; - void operator=(const MCFragment&) LLVM_DELETED_FUNCTION; + MCFragment(const MCFragment &) = delete; + void operator=(const MCFragment &) = delete; public: enum FragmentType { @@ -65,14 +66,14 @@ public: private: FragmentType Kind; - /// Parent - The data for the section this fragment is in. - MCSectionData *Parent; + /// The data for the section this fragment is in. + MCSection *Parent; /// Atom - The atom this fragment is in, as represented by it's defining /// symbol. - MCSymbolData *Atom; + const MCSymbol *Atom; - /// @name Assembler Backend Data + /// \name Assembler Backend Data /// @{ // // FIXME: This could all be kept private to the assembler implementation. @@ -87,7 +88,7 @@ private: /// @} protected: - MCFragment(FragmentType _Kind, MCSectionData *_Parent = nullptr); + MCFragment(FragmentType Kind, MCSection *Parent = nullptr); public: // Only for sentinel. @@ -96,11 +97,11 @@ public: FragmentType getKind() const { return Kind; } - MCSectionData *getParent() const { return Parent; } - void setParent(MCSectionData *Value) { Parent = Value; } + MCSection *getParent() const { return Parent; } + void setParent(MCSection *Value) { Parent = Value; } - MCSymbolData *getAtom() const { return Atom; } - void setAtom(MCSymbolData *Value) { Atom = Value; } + const MCSymbol *getAtom() const { return Atom; } + void setAtom(const MCSymbol *Value) { Atom = Value; } unsigned getLayoutOrder() const { return LayoutOrder; } void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } @@ -111,21 +112,18 @@ public: /// \brief Should this fragment be placed at the end of an aligned bundle? virtual bool alignToBundleEnd() const { return false; } - virtual void setAlignToBundleEnd(bool V) { } + virtual void setAlignToBundleEnd(bool V) {} /// \brief 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. - virtual uint8_t getBundlePadding() const { - return 0; - } + virtual uint8_t getBundlePadding() const { return 0; } /// \brief Set the padding size for this fragment. By default it's a no-op, /// and only some fragments have a meaningful implementation. - virtual void setBundlePadding(uint8_t N) { - } + virtual void setBundlePadding(uint8_t N) {} void dump(); }; @@ -137,33 +135,28 @@ class MCEncodedFragment : public MCFragment { virtual void anchor(); uint8_t BundlePadding; + public: - MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = nullptr) - : MCFragment(FType, SD), BundlePadding(0) - { - } - virtual ~MCEncodedFragment(); + MCEncodedFragment(MCFragment::FragmentType FType, MCSection *Sec = nullptr) + : MCFragment(FType, Sec), BundlePadding(0) {} + ~MCEncodedFragment() override; virtual SmallVectorImpl<char> &getContents() = 0; virtual const SmallVectorImpl<char> &getContents() const = 0; - uint8_t getBundlePadding() const override { - return BundlePadding; - } + uint8_t getBundlePadding() const override { return BundlePadding; } - void setBundlePadding(uint8_t N) override { - BundlePadding = N; - } + void setBundlePadding(uint8_t N) override { BundlePadding = N; } static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); switch (Kind) { - default: - return false; - case MCFragment::FT_Relaxable: - case MCFragment::FT_CompactEncodedInst: - case MCFragment::FT_Data: - return true; + default: + return false; + case MCFragment::FT_Relaxable: + case MCFragment::FT_CompactEncodedInst: + case MCFragment::FT_Data: + return true; } } }; @@ -176,12 +169,10 @@ class MCEncodedFragmentWithFixups : public MCEncodedFragment { public: MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, - MCSectionData *SD = nullptr) - : MCEncodedFragment(FType, SD) - { - } + MCSection *Sec = nullptr) + : MCEncodedFragment(FType, Sec) {} - virtual ~MCEncodedFragmentWithFixups(); + ~MCEncodedFragmentWithFixups() override; typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; @@ -190,7 +181,7 @@ public: virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; virtual fixup_iterator fixup_begin() = 0; - virtual const_fixup_iterator fixup_begin() const = 0; + virtual const_fixup_iterator fixup_begin() const = 0; virtual fixup_iterator fixup_end() = 0; virtual const_fixup_iterator fixup_end() const = 0; @@ -215,25 +206,18 @@ class MCDataFragment : public MCEncodedFragmentWithFixups { /// Fixups - The list of fixups in this fragment. SmallVector<MCFixup, 4> Fixups; + public: - MCDataFragment(MCSectionData *SD = nullptr) - : MCEncodedFragmentWithFixups(FT_Data, SD), - HasInstructions(false), AlignToBundleEnd(false) - { - } + MCDataFragment(MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups(FT_Data, Sec), HasInstructions(false), + AlignToBundleEnd(false) {} SmallVectorImpl<char> &getContents() override { return Contents; } - const SmallVectorImpl<char> &getContents() const override { - return Contents; - } + const SmallVectorImpl<char> &getContents() const override { return Contents; } - SmallVectorImpl<MCFixup> &getFixups() override { - return Fixups; - } + SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; } - const SmallVectorImpl<MCFixup> &getFixups() const override { - return Fixups; - } + const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; } bool hasInstructions() const override { return HasInstructions; } virtual void setHasInstructions(bool V) { HasInstructions = V; } @@ -244,8 +228,8 @@ public: fixup_iterator fixup_begin() override { return Fixups.begin(); } const_fixup_iterator fixup_begin() const override { return Fixups.begin(); } - fixup_iterator fixup_end() override {return Fixups.end();} - const_fixup_iterator fixup_end() const override {return Fixups.end();} + fixup_iterator fixup_end() override { return Fixups.end(); } + const_fixup_iterator fixup_end() const override { return Fixups.end(); } static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; @@ -264,15 +248,13 @@ class MCCompactEncodedInstFragment : public MCEncodedFragment { bool AlignToBundleEnd; SmallVector<char, 4> Contents; + public: - MCCompactEncodedInstFragment(MCSectionData *SD = nullptr) - : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false) - { + MCCompactEncodedInstFragment(MCSection *Sec = nullptr) + : MCEncodedFragment(FT_CompactEncodedInst, Sec), AlignToBundleEnd(false) { } - bool hasInstructions() const override { - return true; - } + bool hasInstructions() const override { return true; } SmallVectorImpl<char> &getContents() override { return Contents; } const SmallVectorImpl<char> &getContents() const override { return Contents; } @@ -306,35 +288,29 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups { SmallVector<MCFixup, 1> Fixups; public: - MCRelaxableFragment(const MCInst &_Inst, - const MCSubtargetInfo &_STI, - MCSectionData *SD = nullptr) - : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst), STI(_STI) { - } + MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, + MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups(FT_Relaxable, Sec), Inst(Inst), STI(STI) {} SmallVectorImpl<char> &getContents() override { return Contents; } const SmallVectorImpl<char> &getContents() const override { return Contents; } const MCInst &getInst() const { return Inst; } - void setInst(const MCInst& Value) { Inst = Value; } + void setInst(const MCInst &Value) { Inst = Value; } const MCSubtargetInfo &getSubtargetInfo() { return STI; } - SmallVectorImpl<MCFixup> &getFixups() override { - return Fixups; - } + SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; } - const SmallVectorImpl<MCFixup> &getFixups() const override { - return Fixups; - } + const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; } bool hasInstructions() const override { return true; } fixup_iterator fixup_begin() override { return Fixups.begin(); } const_fixup_iterator fixup_begin() const override { return Fixups.begin(); } - fixup_iterator fixup_end() override {return Fixups.end();} - const_fixup_iterator fixup_end() const override {return Fixups.end();} + fixup_iterator fixup_end() override { return Fixups.end(); } + const_fixup_iterator fixup_end() const override { return Fixups.end(); } static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Relaxable; @@ -363,13 +339,12 @@ class MCAlignFragment : public MCFragment { bool EmitNops : 1; public: - MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, - unsigned _MaxBytesToEmit, MCSectionData *SD = nullptr) - : MCFragment(FT_Align, SD), Alignment(_Alignment), - Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} + MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, + unsigned MaxBytesToEmit, MCSection *Sec = nullptr) + : MCFragment(FT_Align, Sec), Alignment(Alignment), Value(Value), + ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit), EmitNops(false) {} - /// @name Accessors + /// \name Accessors /// @{ unsigned getAlignment() const { return Alignment; } @@ -404,15 +379,15 @@ class MCFillFragment : public MCFragment { uint64_t Size; public: - MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Size, - MCSectionData *SD = nullptr) - : MCFragment(FT_Fill, SD), - Value(_Value), ValueSize(_ValueSize), Size(_Size) { + MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size, + MCSection *Sec = nullptr) + : MCFragment(FT_Fill, Sec), Value(Value), ValueSize(ValueSize), + Size(Size) { assert((!ValueSize || (Size % ValueSize) == 0) && "Fill size must be a multiple of the value size!"); } - /// @name Accessors + /// \name Accessors /// @{ int64_t getValue() const { return Value; } @@ -438,12 +413,10 @@ class MCOrgFragment : public MCFragment { int8_t Value; public: - MCOrgFragment(const MCExpr &_Offset, int8_t _Value, - MCSectionData *SD = nullptr) - : MCFragment(FT_Org, SD), - Offset(&_Offset), Value(_Value) {} + MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSection *Sec = nullptr) + : MCFragment(FT_Org, Sec), Offset(&Offset), Value(Value) {} - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getOffset() const { return *Offset; } @@ -467,13 +440,14 @@ class MCLEBFragment : public MCFragment { bool IsSigned; SmallString<8> Contents; + public: - MCLEBFragment(const MCExpr &Value_, bool IsSigned_, - MCSectionData *SD = nullptr) - : MCFragment(FT_LEB, SD), - Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) + : MCFragment(FT_LEB, Sec), Value(&Value_), IsSigned(IsSigned_) { + Contents.push_back(0); + } - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getValue() const { return *Value; } @@ -504,12 +478,13 @@ class MCDwarfLineAddrFragment : public MCFragment { SmallString<8> Contents; public: - MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, - MCSectionData *SD = nullptr) - : MCFragment(FT_Dwarf, SD), - LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } + MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, + MCSection *Sec = nullptr) + : MCFragment(FT_Dwarf, Sec), LineDelta(LineDelta), AddrDelta(&AddrDelta) { + Contents.push_back(0); + } - /// @name Accessors + /// \name Accessors /// @{ int64_t getLineDelta() const { return LineDelta; } @@ -536,12 +511,12 @@ class MCDwarfCallFrameFragment : public MCFragment { SmallString<8> Contents; public: - MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, - MCSectionData *SD = nullptr) - : MCFragment(FT_DwarfFrame, SD), - AddrDelta(&_AddrDelta) { Contents.push_back(0); } + MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) + : MCFragment(FT_DwarfFrame, Sec), AddrDelta(&AddrDelta) { + Contents.push_back(0); + } - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getAddrDelta() const { return *AddrDelta; } @@ -556,265 +531,10 @@ public: } }; -// FIXME: Should this be a separate class, or just merged into MCSection? Since -// we anticipate the fast path being through an MCAssembler, the only reason to -// keep it out is for API abstraction. -class MCSectionData : public ilist_node<MCSectionData> { - friend class MCAsmLayout; - - MCSectionData(const MCSectionData&) LLVM_DELETED_FUNCTION; - void operator=(const MCSectionData&) LLVM_DELETED_FUNCTION; - -public: - typedef iplist<MCFragment> FragmentListType; - - typedef FragmentListType::const_iterator const_iterator; - typedef FragmentListType::iterator iterator; - - typedef FragmentListType::const_reverse_iterator const_reverse_iterator; - typedef FragmentListType::reverse_iterator reverse_iterator; - - /// \brief Express the state of bundle locked groups while emitting code. - enum BundleLockStateType { - NotBundleLocked, - BundleLocked, - BundleLockedAlignToEnd - }; -private: - FragmentListType Fragments; - const MCSection *Section; - - /// Ordinal - The section index in the assemblers section list. - unsigned Ordinal; - - /// LayoutOrder - The index of this section in the layout order. - unsigned LayoutOrder; - - /// Alignment - The maximum alignment seen in this section. - unsigned Alignment; - - /// \brief Keeping track of bundle-locked state. - BundleLockStateType BundleLockState; - - /// \brief Current nesting depth of bundle_lock directives. - unsigned BundleLockNestingDepth; - - /// \brief We've seen a bundle_lock directive but not its first instruction - /// yet. - bool BundleGroupBeforeFirstInst; - - /// @name Assembler Backend Data - /// @{ - // - // FIXME: This could all be kept private to the assembler implementation. - - /// HasInstructions - Whether this section has had instructions emitted into - /// it. - unsigned HasInstructions : 1; - - /// Mapping from subsection number to insertion point for subsection numbers - /// below that number. - SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap; - - /// @} - -public: - // Only for use as sentinel. - MCSectionData(); - MCSectionData(const MCSection &Section, MCAssembler *A = nullptr); - - const MCSection &getSection() const { return *Section; } - - unsigned getAlignment() const { return Alignment; } - void setAlignment(unsigned Value) { Alignment = Value; } - - bool hasInstructions() const { return HasInstructions; } - void setHasInstructions(bool Value) { HasInstructions = Value; } - - unsigned getOrdinal() const { return Ordinal; } - void setOrdinal(unsigned Value) { Ordinal = Value; } - - unsigned getLayoutOrder() const { return LayoutOrder; } - void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } - - /// @name Fragment Access - /// @{ - - const FragmentListType &getFragmentList() const { return Fragments; } - FragmentListType &getFragmentList() { return Fragments; } - - iterator begin() { return Fragments.begin(); } - const_iterator begin() const { return Fragments.begin(); } - - iterator end() { return Fragments.end(); } - const_iterator end() const { return Fragments.end(); } - - reverse_iterator rbegin() { return Fragments.rbegin(); } - const_reverse_iterator rbegin() const { return Fragments.rbegin(); } - - reverse_iterator rend() { return Fragments.rend(); } - const_reverse_iterator rend() const { return Fragments.rend(); } - - size_t size() const { return Fragments.size(); } - - bool empty() const { return Fragments.empty(); } - - iterator getSubsectionInsertionPoint(unsigned Subsection); - - bool isBundleLocked() const { - return BundleLockState != NotBundleLocked; - } - - BundleLockStateType getBundleLockState() const { - return BundleLockState; - } - - void setBundleLockState(BundleLockStateType NewState); - - bool isBundleGroupBeforeFirstInst() const { - return BundleGroupBeforeFirstInst; - } - - void setBundleGroupBeforeFirstInst(bool IsFirst) { - BundleGroupBeforeFirstInst = IsFirst; - } - - void dump(); - - /// @} -}; - -// FIXME: Same concerns as with SectionData. -class MCSymbolData : public ilist_node<MCSymbolData> { - const MCSymbol *Symbol; - - /// Fragment - The fragment this symbol's value is relative to, if any. Also - /// stores if this symbol is visible outside this translation unit (bit 0) or - /// if it is private extern (bit 1). - PointerIntPair<MCFragment *, 2> Fragment; - - union { - /// Offset - The offset to apply to the fragment address to form this - /// symbol's value. - uint64_t Offset; - - /// CommonSize - The size of the symbol, if it is 'common'. - uint64_t CommonSize; - }; - - /// SymbolSize - An expression describing how to calculate the size of - /// a symbol. If a symbol has no size this field will be NULL. - const MCExpr *SymbolSize; - - /// CommonAlign - The alignment of the symbol, if it is 'common', or -1. - // - // FIXME: Pack this in with other fields? - unsigned CommonAlign; - - /// Flags - The Flags field is used by object file implementations to store - /// additional per symbol information which is not easily classified. - uint32_t Flags; - - /// Index - Index field, for use by the object file implementation. - uint64_t Index; - -public: - // Only for use as sentinel. - MCSymbolData(); - MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, - MCAssembler *A = nullptr); - - /// @name Accessors - /// @{ - - const MCSymbol &getSymbol() const { return *Symbol; } - - MCFragment *getFragment() const { return Fragment.getPointer(); } - void setFragment(MCFragment *Value) { Fragment.setPointer(Value); } - - uint64_t getOffset() const { - assert(!isCommon()); - return Offset; - } - void setOffset(uint64_t Value) { - assert(!isCommon()); - Offset = Value; - } - - /// @} - /// @name Symbol Attributes - /// @{ - - bool isExternal() const { return Fragment.getInt() & 1; } - void setExternal(bool Value) { - Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value)); - } - - bool isPrivateExtern() const { return Fragment.getInt() & 2; } - void setPrivateExtern(bool Value) { - Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1)); - } - - /// isCommon - Is this a 'common' symbol. - bool isCommon() const { return CommonAlign != -1U; } - - /// setCommon - Mark this symbol as being 'common'. - /// - /// \param Size - The size of the symbol. - /// \param Align - The alignment of the symbol. - void setCommon(uint64_t Size, unsigned Align) { - assert(getOffset() == 0); - CommonSize = Size; - CommonAlign = Align; - } - - /// getCommonSize - Return the size of a 'common' symbol. - uint64_t getCommonSize() const { - assert(isCommon() && "Not a 'common' symbol!"); - return CommonSize; - } - - void setSize(const MCExpr *SS) { - SymbolSize = SS; - } - - const MCExpr *getSize() const { - return SymbolSize; - } - - - /// getCommonAlignment - Return the alignment of a 'common' symbol. - unsigned getCommonAlignment() const { - assert(isCommon() && "Not a 'common' symbol!"); - return CommonAlign; - } - - /// getFlags - Get the (implementation defined) symbol flags. - uint32_t getFlags() const { return Flags; } - - /// setFlags - Set the (implementation defined) symbol flags. - void setFlags(uint32_t Value) { Flags = Value; } - - /// modifyFlags - Modify the flags via a mask - void modifyFlags(uint32_t Value, uint32_t Mask) { - Flags = (Flags & ~Mask) | Value; - } - - /// getIndex - Get the (implementation defined) index. - uint64_t getIndex() const { return Index; } - - /// setIndex - Set the (implementation defined) index. - void setIndex(uint64_t Value) { Index = Value; } - - /// @} - - void dump() const; -}; - // FIXME: This really doesn't belong here. See comments below. struct IndirectSymbolData { MCSymbol *Symbol; - MCSectionData *SectionData; + MCSection *Section; }; // FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk @@ -831,14 +551,15 @@ class MCAssembler { friend class MCAsmLayout; public: - typedef iplist<MCSectionData> SectionDataListType; - typedef iplist<MCSymbolData> SymbolDataListType; + typedef SetVector<MCSection *> SectionListType; + typedef std::vector<const MCSymbol *> SymbolDataListType; - typedef SectionDataListType::const_iterator const_iterator; - typedef SectionDataListType::iterator iterator; + typedef pointee_iterator<SectionListType::const_iterator> const_iterator; + typedef pointee_iterator<SectionListType::iterator> iterator; - typedef SymbolDataListType::const_iterator const_symbol_iterator; - typedef SymbolDataListType::iterator symbol_iterator; + typedef pointee_iterator<SymbolDataListType::const_iterator> + const_symbol_iterator; + typedef pointee_iterator<SymbolDataListType::iterator> symbol_iterator; typedef iterator_range<symbol_iterator> symbol_range; typedef iterator_range<const_symbol_iterator> const_symbol_range; @@ -847,11 +568,11 @@ public: typedef FileNameVectorType::const_iterator const_file_name_iterator; typedef std::vector<IndirectSymbolData>::const_iterator - const_indirect_symbol_iterator; + const_indirect_symbol_iterator; typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator; typedef std::vector<DataRegionData>::const_iterator - const_data_region_iterator; + const_data_region_iterator; typedef std::vector<DataRegionData>::iterator data_region_iterator; /// MachO specific deployment target version info. @@ -863,9 +584,10 @@ public: unsigned Minor; unsigned Update; } VersionMinInfoType; + private: - MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION; - void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION; + MCAssembler(const MCAssembler &) = delete; + void operator=(const MCAssembler &) = delete; MCContext &Context; @@ -877,26 +599,18 @@ private: raw_ostream &OS; - iplist<MCSectionData> Sections; + SectionListType Sections; - iplist<MCSymbolData> Symbols; + SymbolDataListType Symbols; - /// The map of sections to their associated assembler backend data. - // - // FIXME: Avoid this indirection? - DenseMap<const MCSection*, MCSectionData*> SectionMap; - - /// The map of symbols to their associated assembler backend data. - // - // FIXME: Avoid this indirection? - DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap; + DenseSet<const MCSymbol *> LocalsUsedInReloc; std::vector<IndirectSymbolData> IndirectSymbols; std::vector<DataRegionData> DataRegions; /// The list of linker options to propagate into the object file. - std::vector<std::vector<std::string> > LinkerOptions; + std::vector<std::vector<std::string>> LinkerOptions; /// List of declared file names FileNameVectorType FileNames; @@ -908,7 +622,7 @@ private: // here. Maybe when the relocation stuff moves to target specific, // this can go with it? The streamer would need some target specific // refactoring too. - mutable SmallPtrSet<const MCSymbol*, 64> ThumbFuncs; + mutable SmallPtrSet<const MCSymbol *, 64> ThumbFuncs; /// \brief The bundle alignment size currently set in the assembler. /// @@ -930,6 +644,7 @@ private: MCLOHContainer LOHContainer; VersionMinInfoType VersionMinInfo; + private: /// Evaluate a fixup to a relocatable expression and the value which should be /// placed into the fixup. @@ -944,9 +659,9 @@ private: /// \return Whether the fixup value was fully resolved. This is true if the /// \p Value result is fixed, otherwise the value may change due to /// relocation. - bool evaluateFixup(const MCAsmLayout &Layout, - const MCFixup &Fixup, const MCFragment *DF, - MCValue &Target, uint64_t &Value) const; + bool evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, + const MCFragment *DF, MCValue &Target, + uint64_t &Value) const; /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). @@ -963,7 +678,7 @@ private: /// \brief Perform one layout iteration of the given section and return true /// if any offsets were adjusted. - bool layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); + bool layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec); bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF); @@ -980,6 +695,9 @@ private: MCFragment &F, const MCFixup &Fixup); public: + void addLocalUsedInReloc(const MCSymbol &Sym); + bool isLocalUsedInReloc(const MCSymbol &Sym) const; + /// Compute the effective fragment size assuming it is laid out at the given /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, @@ -987,7 +705,7 @@ public: /// Find the symbol which defines the atom containing the given symbol, or /// null if there is no such symbol. - const MCSymbolData *getAtom(const MCSymbolData *Symbol) const; + const MCSymbol *getAtom(const MCSymbol &S) const; /// Check whether a particular symbol is visible to the linker and is required /// in the symbol table, or whether it can be discarded by the assembler. This @@ -996,7 +714,7 @@ public: bool isSymbolLinkerVisible(const MCSymbol &SD) const; /// Emit the section contents using the given object writer. - void writeSectionData(const MCSectionData *Section, + void writeSectionData(const MCSection *Section, const MCAsmLayout &Layout) const; /// Check whether a given symbol has been flagged with .thumb_func. @@ -1006,8 +724,8 @@ public: void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } /// ELF e_header flags - unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;} - void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;} + unsigned getELFHeaderEFlags() const { return ELFHeaderEFlags; } + void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; } /// MachO deployment target version information. const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; } @@ -1051,36 +769,25 @@ public: void Finish(); // FIXME: This does not belong here. - bool getSubsectionsViaSymbols() const { - return SubsectionsViaSymbols; - } - void setSubsectionsViaSymbols(bool Value) { - SubsectionsViaSymbols = Value; - } + bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; } + void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; } bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } - bool isBundlingEnabled() const { - return BundleAlignSize != 0; - } + bool isBundlingEnabled() const { return BundleAlignSize != 0; } - unsigned getBundleAlignSize() const { - return BundleAlignSize; - } + unsigned getBundleAlignSize() const { return BundleAlignSize; } void setBundleAlignSize(unsigned Size) { - assert((Size == 0 || !(Size & (Size - 1))) && + assert((Size == 0 || !(Size & (Size - 1))) && "Expect a power-of-two bundle align size"); BundleAlignSize = Size; } - /// @name Section List Access + /// \name Section List Access /// @{ - const SectionDataListType &getSectionList() const { return Sections; } - SectionDataListType &getSectionList() { return Sections; } - iterator begin() { return Sections.begin(); } const_iterator begin() const { return Sections.begin(); } @@ -1090,12 +797,8 @@ public: size_t size() const { return Sections.size(); } /// @} - /// @name Symbol List Access + /// \name Symbol List Access /// @{ - - const SymbolDataListType &getSymbolList() const { return Symbols; } - SymbolDataListType &getSymbolList() { return Symbols; } - symbol_iterator symbol_begin() { return Symbols.begin(); } const_symbol_iterator symbol_begin() const { return Symbols.begin(); } @@ -1103,12 +806,14 @@ public: const_symbol_iterator symbol_end() const { return Symbols.end(); } symbol_range symbols() { return make_range(symbol_begin(), symbol_end()); } - const_symbol_range symbols() const { return make_range(symbol_begin(), symbol_end()); } + const_symbol_range symbols() const { + return make_range(symbol_begin(), symbol_end()); + } size_t symbol_size() const { return Symbols.size(); } /// @} - /// @name Indirect Symbol List Access + /// \name Indirect Symbol List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are @@ -1135,34 +840,28 @@ public: size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} - /// @name Linker Option List Access + /// \name Linker Option List Access /// @{ - std::vector<std::vector<std::string> > &getLinkerOptions() { + std::vector<std::vector<std::string>> &getLinkerOptions() { return LinkerOptions; } /// @} - /// @name Data Region List Access + /// \name Data Region List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are // factored so that the streamer has direct access to the .o writer, it can // disappear. - std::vector<DataRegionData> &getDataRegions() { - return DataRegions; - } + std::vector<DataRegionData> &getDataRegions() { return DataRegions; } - data_region_iterator data_region_begin() { - return DataRegions.begin(); - } + data_region_iterator data_region_begin() { return DataRegions.begin(); } const_data_region_iterator data_region_begin() const { return DataRegions.begin(); } - data_region_iterator data_region_end() { - return DataRegions.end(); - } + data_region_iterator data_region_end() { return DataRegions.end(); } const_data_region_iterator data_region_end() const { return DataRegions.end(); } @@ -1170,42 +869,23 @@ public: size_t data_region_size() const { return DataRegions.size(); } /// @} - /// @name Data Region List Access + /// \name Data Region List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are // factored so that the streamer has direct access to the .o writer, it can // disappear. - MCLOHContainer & getLOHContainer() { - return LOHContainer; - } - const MCLOHContainer & getLOHContainer() const { + MCLOHContainer &getLOHContainer() { return LOHContainer; } + const MCLOHContainer &getLOHContainer() const { return const_cast<MCAssembler *>(this)->getLOHContainer(); } /// @} - /// @name Backend Data Access + /// \name Backend Data Access /// @{ - MCSectionData &getSectionData(const MCSection &Section) const { - MCSectionData *Entry = SectionMap.lookup(&Section); - assert(Entry && "Missing section data!"); - return *Entry; - } - - MCSectionData &getOrCreateSectionData(const MCSection &Section, - bool *Created = nullptr) { - MCSectionData *&Entry = SectionMap[&Section]; + bool registerSection(MCSection &Section) { return Sections.insert(&Section); } - if (Created) *Created = !Entry; - if (!Entry) - Entry = new MCSectionData(Section, this); - - return *Entry; - } - - bool hasSymbolData(const MCSymbol &Symbol) const { - return SymbolMap.lookup(&Symbol) != nullptr; - } + bool hasSymbolData(const MCSymbol &Symbol) const { return Symbol.hasData(); } MCSymbolData &getSymbolData(const MCSymbol &Symbol) { return const_cast<MCSymbolData &>( @@ -1213,29 +893,25 @@ public: } const MCSymbolData &getSymbolData(const MCSymbol &Symbol) const { - MCSymbolData *Entry = SymbolMap.lookup(&Symbol); - assert(Entry && "Missing symbol data!"); - return *Entry; + return Symbol.getData(); } MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol, bool *Created = nullptr) { - MCSymbolData *&Entry = SymbolMap[&Symbol]; - - if (Created) *Created = !Entry; - if (!Entry) - Entry = new MCSymbolData(Symbol, nullptr, 0, this); - - return *Entry; + if (Created) + *Created = !hasSymbolData(Symbol); + if (!hasSymbolData(Symbol)) { + Symbol.initializeData(); + Symbols.push_back(&Symbol); + } + return Symbol.getData(); } const_file_name_iterator file_names_begin() const { return FileNames.begin(); } - const_file_name_iterator file_names_end() const { - return FileNames.end(); - } + const_file_name_iterator file_names_end() const { return FileNames.end(); } void addFileName(StringRef FileName) { if (std::find(file_names_begin(), file_names_end(), FileName) == @@ -1243,11 +919,22 @@ public: FileNames.push_back(FileName); } + /// \brief Write the necessary bundle padding to the given object writer. + /// Expects a fragment \p F containing instructions and its size \p FSize. + void writeFragmentPadding(const MCFragment &F, uint64_t FSize, + MCObjectWriter *OW) const; + /// @} void dump(); }; +/// \brief 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. +uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F, + uint64_t FOffset, uint64_t FSize); + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index d3b56177d50a7..b6c19150c12a5 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -22,8 +22,9 @@ template<typename T> class SmallVectorImpl; /// MCCodeEmitter - Generic instruction encoding interface. class MCCodeEmitter { private: - MCCodeEmitter(const MCCodeEmitter &) LLVM_DELETED_FUNCTION; - void operator=(const MCCodeEmitter &) LLVM_DELETED_FUNCTION; + MCCodeEmitter(const MCCodeEmitter &) = delete; + void operator=(const MCCodeEmitter &) = delete; + protected: // Can only create subclasses. MCCodeEmitter(); @@ -31,11 +32,11 @@ public: virtual ~MCCodeEmitter(); /// Lifetime management - virtual void reset() { } + virtual void reset() {} /// EncodeInstruction - Encode the given \p Inst to bytes on the output /// stream \p OS. - virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS, + virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const = 0; }; diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h index 84ce934d822ee..0a4744f1d0f7d 100644 --- a/include/llvm/MC/MCCodeGenInfo.h +++ b/include/llvm/MC/MCCodeGenInfo.h @@ -19,33 +19,33 @@ namespace llvm { - class MCCodeGenInfo { - /// RelocationModel - Relocation model: static, pic, etc. - /// - Reloc::Model RelocationModel; +class MCCodeGenInfo { + /// RelocationModel - Relocation model: static, pic, etc. + /// + Reloc::Model RelocationModel; - /// CMModel - Code model. - /// - CodeModel::Model CMModel; + /// CMModel - Code model. + /// + CodeModel::Model CMModel; - /// OptLevel - Optimization level. - /// - CodeGenOpt::Level OptLevel; + /// OptLevel - Optimization level. + /// + CodeGenOpt::Level OptLevel; - public: - void InitMCCodeGenInfo(Reloc::Model RM = Reloc::Default, - CodeModel::Model CM = CodeModel::Default, - CodeGenOpt::Level OL = CodeGenOpt::Default); +public: + void initMCCodeGenInfo(Reloc::Model RM = Reloc::Default, + CodeModel::Model CM = CodeModel::Default, + CodeGenOpt::Level OL = CodeGenOpt::Default); - Reloc::Model getRelocationModel() const { return RelocationModel; } + Reloc::Model getRelocationModel() const { return RelocationModel; } - CodeModel::Model getCodeModel() const { return CMModel; } + CodeModel::Model getCodeModel() const { return CMModel; } - CodeGenOpt::Level getOptLevel() const { return OptLevel; } + CodeGenOpt::Level getOptLevel() const { return OptLevel; } - // Allow overriding OptLevel on a per-function basis. - void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } - }; + // Allow overriding OptLevel on a per-function basis. + void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } +}; } // namespace llvm #endif diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index e3163a7946a79..5b57b9d448e81 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -15,8 +15,8 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCStreamer.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" @@ -37,20 +37,20 @@ namespace llvm { class MCRegisterInfo; class MCLineSection; class SMLoc; - class StringRef; - class Twine; class MCSectionMachO; class MCSectionELF; class MCSectionCOFF; - /// MCContext - Context object for machine code objects. This class owns all - /// of the sections that it creates. + /// Context object for machine code objects. This class owns all of the + /// sections that it creates. /// class MCContext { - MCContext(const MCContext&) LLVM_DELETED_FUNCTION; - MCContext &operator=(const MCContext&) LLVM_DELETED_FUNCTION; + MCContext(const MCContext &) = delete; + MCContext &operator=(const MCContext &) = delete; + public: - typedef StringMap<MCSymbol*, BumpPtrAllocator&> SymbolTable; + typedef StringMap<MCSymbol *, BumpPtrAllocator &> SymbolTable; + private: /// The SourceMgr for this object, if any. const SourceMgr *SrcMgr; @@ -64,34 +64,34 @@ namespace llvm { /// The MCObjectFileInfo for this target. const MCObjectFileInfo *MOFI; - /// Allocator - Allocator object used for creating machine code objects. + /// Allocator object used for creating machine code objects. /// /// We use a bump pointer allocator to avoid the need to track all allocated /// objects. BumpPtrAllocator Allocator; - /// Symbols - Bindings of names to symbols. + /// Bindings of names to symbols. SymbolTable Symbols; /// ELF sections can have a corresponding symbol. This maps one to the /// other. - DenseMap<const MCSectionELF*, MCSymbol*> SectionSymbols; + DenseMap<const MCSectionELF *, MCSymbol *> SectionSymbols; - /// A maping from a local label number and an instance count to a symbol. + /// A mapping from a local label number and an instance count to a symbol. /// For example, in the assembly /// 1: /// 2: /// 1: /// We have three labels represented by the pairs (1, 0), (2, 0) and (1, 1) - DenseMap<std::pair<unsigned, unsigned>, MCSymbol*> LocalSymbols; + DenseMap<std::pair<unsigned, unsigned>, MCSymbol *> LocalSymbols; - /// UsedNames - Keeps tracks of names that were used both for used declared - /// and artificial symbols. - StringMap<bool, BumpPtrAllocator&> UsedNames; + /// Keeps tracks of names that were used both for used declared and + /// artificial symbols. + StringMap<bool, BumpPtrAllocator &> UsedNames; - /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary - /// symbol. - unsigned NextUniqueID; + /// The next ID to dole out to an unnamed assembler temporary symbol with + /// a given prefix. + StringMap<unsigned> NextID; /// Instances of directional local labels. DenseMap<unsigned, MCLabel *> Instances; @@ -136,10 +136,8 @@ namespace llvm { /// assembly source files. unsigned GenDwarfFileNumber; - /// Symbols created for the start and end of each section, used for - /// generating the .debug_ranges and .debug_aranges sections. - MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > - SectionStartEndSyms; + /// Sections for generating the .debug_ranges and .debug_aranges sections. + SetVector<MCSection *> SectionsForRanges; /// The information gathered from labels that will have dwarf label /// entries when generating dwarf assembly source files. @@ -160,21 +158,54 @@ namespace llvm { /// differences between temporary and non-temporary labels (primarily on /// Darwin). bool AllowTemporaryLabels; + bool UseNamesOnTempLabels = true; /// The Compile Unit ID that we are currently processing. unsigned DwarfCompileUnitID; - typedef std::pair<std::string, std::string> SectionGroupPair; - typedef std::tuple<std::string, std::string, int> SectionGroupTriple; - - StringMap<const MCSectionMachO*> MachOUniquingMap; - std::map<SectionGroupPair, const MCSectionELF *> ELFUniquingMap; - std::map<SectionGroupTriple, const MCSectionCOFF *> COFFUniquingMap; + struct ELFSectionKey { + std::string SectionName; + StringRef GroupName; + unsigned UniqueID; + ELFSectionKey(StringRef SectionName, StringRef GroupName, + unsigned UniqueID) + : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) { + } + bool operator<(const ELFSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + return UniqueID < Other.UniqueID; + } + }; + + struct COFFSectionKey { + std::string SectionName; + StringRef GroupName; + int SelectionKey; + COFFSectionKey(StringRef SectionName, StringRef GroupName, + int SelectionKey) + : SectionName(SectionName), GroupName(GroupName), + SelectionKey(SelectionKey) {} + bool operator<(const COFFSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + return SelectionKey < Other.SelectionKey; + } + }; + + StringMap<MCSectionMachO *> MachOUniquingMap; + std::map<ELFSectionKey, MCSectionELF *> ELFUniquingMap; + std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap; + StringMap<bool> ELFRelSecNames; /// Do automatic reset in destructor bool AutoReset; - MCSymbol *CreateSymbol(StringRef Name); + MCSymbol *CreateSymbol(StringRef Name, bool AlwaysAddSuffix); MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal, unsigned Instance); @@ -194,8 +225,9 @@ namespace llvm { const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } + void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; } - /// @name Module Lifetime Management + /// \name Module Lifetime Management /// @{ /// reset - return object to right after construction state to prepare @@ -204,104 +236,144 @@ namespace llvm { /// @} - /// @name Symbol Management + /// \name Symbol Management /// @{ - /// CreateLinkerPrivateTempSymbol - Create and return a new linker temporary - /// symbol with a unique but unspecified name. - MCSymbol *CreateLinkerPrivateTempSymbol(); + /// Create and return a new linker temporary symbol with a unique but + /// unspecified name. + MCSymbol *createLinkerPrivateTempSymbol(); - /// CreateTempSymbol - Create and return a new assembler temporary symbol - /// with a unique but unspecified name. - MCSymbol *CreateTempSymbol(); + /// Create and return a new assembler temporary symbol with a unique but + /// unspecified name. + MCSymbol *createTempSymbol(); - /// getUniqueSymbolID() - Return a unique identifier for use in constructing - /// symbol names. - unsigned getUniqueSymbolID() { return NextUniqueID++; } + MCSymbol *createTempSymbol(const Twine &Name, bool AlwaysAddSuffix); /// Create the definition of a directional local symbol for numbered label /// (used for "1:" definitions). - MCSymbol *CreateDirectionalLocalSymbol(unsigned LocalLabelVal); + MCSymbol *createDirectionalLocalSymbol(unsigned LocalLabelVal); /// Create and return a directional local symbol for numbered label (used /// for "1b" or 1f" references). - MCSymbol *GetDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before); + MCSymbol *getDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before); - /// GetOrCreateSymbol - Lookup the symbol inside with the specified - /// @p Name. If it exists, return it. If not, create a forward - /// reference and return it. + /// Lookup the symbol inside with the specified \p Name. If it exists, + /// return it. If not, create a forward reference and return it. /// - /// @param Name - The symbol name, which must be unique across all symbols. - MCSymbol *GetOrCreateSymbol(StringRef Name); - MCSymbol *GetOrCreateSymbol(const Twine &Name); + /// \param Name - The symbol name, which must be unique across all symbols. + MCSymbol *getOrCreateSymbol(const Twine &Name); MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); - MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName); + /// Gets a symbol that will be defined to the final stack offset of a local + /// variable after codegen. + /// + /// \param Idx - The index of a local variable passed to @llvm.frameescape. + MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx); + + MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName); + + MCSymbol *getOrCreateLSDASymbol(StringRef FuncName); - /// LookupSymbol - Get the symbol for \p Name, or null. - MCSymbol *LookupSymbol(StringRef Name) const; - MCSymbol *LookupSymbol(const Twine &Name) const; + /// Get the symbol for \p Name, or null. + MCSymbol *lookupSymbol(const Twine &Name) const; /// getSymbols - Get a reference for the symbol table for clients that /// want to, for example, iterate over all symbols. 'const' because we /// still want any modifications to the table itself to use the MCContext /// APIs. - const SymbolTable &getSymbols() const { - return Symbols; - } + const SymbolTable &getSymbols() const { return Symbols; } /// @} - /// @name Section Management + /// \name Section Management /// @{ - /// getMachOSection - Return the MCSection for the specified mach-o section. - /// This requires the operands to be valid. - const MCSectionMachO *getMachOSection(StringRef Segment, - StringRef Section, - unsigned TypeAndAttributes, - unsigned Reserved2, - SectionKind K); - const MCSectionMachO *getMachOSection(StringRef Segment, - StringRef Section, - unsigned TypeAndAttributes, - SectionKind K) { - return getMachOSection(Segment, Section, TypeAndAttributes, 0, K); + /// Return the MCSection for the specified mach-o section. This requires + /// the operands to be valid. + MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind K, + const char *BeginSymName = nullptr); + + MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, SectionKind K, + const char *BeginSymName = nullptr) { + return getMachOSection(Segment, Section, TypeAndAttributes, 0, K, + BeginSymName); } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags) { + return getELFSection(Section, Type, Flags, nullptr); + } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind, - unsigned EntrySize, StringRef Group); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, const char *BeginSymName) { + return getELFSection(Section, Type, Flags, 0, "", BeginSymName); + } - void renameELFSection(const MCSectionELF *Section, StringRef Name); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group) { + return getELFSection(Section, Type, Flags, EntrySize, Group, nullptr); + } - const MCSectionELF *CreateELFGroupSection(); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, const char *BeginSymName) { + return getELFSection(Section, Type, Flags, EntrySize, Group, ~0, + BeginSymName); + } - const MCSectionCOFF *getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind, - StringRef COMDATSymName, int Selection); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, unsigned UniqueID) { + return getELFSection(Section, Type, Flags, EntrySize, Group, UniqueID, + nullptr); + } - const MCSectionCOFF *getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, unsigned UniqueID, + const char *BeginSymName); - const MCSectionCOFF *getCOFFSection(StringRef Section); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + const MCSymbol *Group, unsigned UniqueID, + const char *BeginSymName, + const MCSectionELF *Associated); + + MCSectionELF *createELFRelSection(StringRef Name, unsigned Type, + unsigned Flags, unsigned EntrySize, + const MCSymbol *Group, + const MCSectionELF *Associated); + + void renameELFSection(MCSectionELF *Section, StringRef Name); + + MCSectionELF *createELFGroupSection(const MCSymbol *Group); + + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, StringRef COMDATSymName, + int Selection, + const char *BeginSymName = nullptr); + + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, + const char *BeginSymName = nullptr); + + MCSectionCOFF *getCOFFSection(StringRef Section); /// Gets or creates a section equivalent to Sec that is associated with the /// section containing KeySym. For example, to create a debug info section /// associated with an inline function, pass the normal debug info section /// as Sec and the function symbol as KeySym. - const MCSectionCOFF *getAssociativeCOFFSection(const MCSectionCOFF *Sec, - const MCSymbol *KeySym); + MCSectionCOFF *getAssociativeCOFFSection(MCSectionCOFF *Sec, + const MCSymbol *KeySym); /// @} - /// @name Dwarf Management + /// \name Dwarf Management /// @{ /// \brief Get the compilation directory for DW_AT_comp_dir @@ -323,8 +395,8 @@ namespace llvm { /// \brief Set the main file name and override the default. void setMainFileName(StringRef S) { MainFileName = S; } - /// GetDwarfFile - creates an entry in the dwarf file and directory tables. - unsigned GetDwarfFile(StringRef Directory, StringRef FileName, + /// Creates an entry in the dwarf file and directory tables. + unsigned getDwarfFile(StringRef Directory, StringRef FileName, unsigned FileNumber, unsigned CUID); bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0); @@ -356,9 +428,7 @@ namespace llvm { return true; return false; } - unsigned getDwarfCompileUnitID() { - return DwarfCompileUnitID; - } + unsigned getDwarfCompileUnitID() { return DwarfCompileUnitID; } void setDwarfCompileUnitID(unsigned CUIndex) { DwarfCompileUnitID = CUIndex; } @@ -366,10 +436,10 @@ namespace llvm { getMCDwarfLineTable(CUID).setCompilationDir(CompilationDir); } - /// setCurrentDwarfLoc - saves the information from the currently parsed - /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction - /// is assembled an entry in the line number table with this information and - /// the address of the instruction will be created. + /// Saves the information from the currently parsed dwarf .loc directive + /// and sets DwarfLocSeen. When the next instruction is assembled an entry + /// in the line number table with this information and the address of the + /// instruction will be created. void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator) { @@ -381,7 +451,7 @@ namespace llvm { CurrentDwarfLoc.setDiscriminator(Discriminator); DwarfLocSeen = true; } - void ClearDwarfLocSeen() { DwarfLocSeen = false; } + void clearDwarfLocSeen() { DwarfLocSeen = false; } bool getDwarfLocSeen() { return DwarfLocSeen; } const MCDwarfLoc &getCurrentDwarfLoc() { return CurrentDwarfLoc; } @@ -392,17 +462,13 @@ namespace llvm { void setGenDwarfFileNumber(unsigned FileNumber) { GenDwarfFileNumber = FileNumber; } - MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > & - getGenDwarfSectionSyms() { - return SectionStartEndSyms; + const SetVector<MCSection *> &getGenDwarfSectionSyms() { + return SectionsForRanges; } - std::pair<MapVector<const MCSection *, - std::pair<MCSymbol *, MCSymbol *> >::iterator, - bool> - addGenDwarfSection(const MCSection *Sec) { - return SectionStartEndSyms.insert( - std::make_pair(Sec, std::make_pair(nullptr, nullptr))); + bool addGenDwarfSection(MCSection *Sec) { + return SectionsForRanges.insert(Sec); } + void finalizeDwarfSections(MCStreamer &MCOS); const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const { return MCGenDwarfLabelEntries; @@ -425,56 +491,52 @@ namespace llvm { char *getSecureLogFile() { return SecureLogFile; } raw_ostream *getSecureLog() { return SecureLog; } bool getSecureLogUsed() { return SecureLogUsed; } - void setSecureLog(raw_ostream *Value) { - SecureLog = Value; - } - void setSecureLogUsed(bool Value) { - SecureLogUsed = Value; - } + void setSecureLog(raw_ostream *Value) { SecureLog = Value; } + void setSecureLogUsed(bool Value) { SecureLogUsed = Value; } - void *Allocate(unsigned Size, unsigned Align = 8) { + void *allocate(unsigned Size, unsigned Align = 8) { return Allocator.Allocate(Size, Align); } - void Deallocate(void *Ptr) { - } + void deallocate(void *Ptr) {} // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. - LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg) const; + LLVM_ATTRIBUTE_NORETURN void reportFatalError(SMLoc L, + const Twine &Msg) const; }; } // end namespace llvm // operator new and delete aren't allowed inside namespaces. // The throw specifications are mandated by the standard. -/// @brief Placement new for using the MCContext's allocator. +/// \brief Placement new for using the MCContext's allocator. /// /// This placement form of operator new uses the MCContext's allocator for /// obtaining memory. It is a non-throwing new, which means that it returns /// null on error. (If that is what the allocator does. The current does, so if /// this ever changes, this operator will have to be changed, too.) /// Usage looks like this (assuming there's an MCContext 'Context' in scope): -/// @code -/// // Default alignment (16) +/// \code +/// // Default alignment (8) /// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); /// // Specific alignment -/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments); -/// @endcode +/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); +/// \endcode /// Please note that you cannot use delete on the pointer; it must be /// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// \c Context.Deallocate(Ptr). /// -/// @param Bytes The number of bytes to allocate. Calculated by the compiler. -/// @param C The MCContext that provides the allocator. -/// @param Alignment The alignment of the allocated memory (if the underlying +/// \param Bytes The number of bytes to allocate. Calculated by the compiler. +/// \param C The MCContext that provides the allocator. +/// \param Alignment The alignment of the allocated memory (if the underlying /// allocator supports it). -/// @return The allocated memory. Could be NULL. +/// \return The allocated memory. Could be NULL. inline void *operator new(size_t Bytes, llvm::MCContext &C, - size_t Alignment = 16) throw () { - return C.Allocate(Bytes, Alignment); + size_t Alignment = 8) throw() { + return C.allocate(Bytes, Alignment); } -/// @brief Placement delete companion to the new above. +/// \brief Placement delete companion to the new above. /// /// This operator is just a companion to the new above. There is no way of /// invoking it directly; see the new operator for more details. This operator @@ -482,41 +544,41 @@ inline void *operator new(size_t Bytes, llvm::MCContext &C, /// the MCContext throws in the object constructor. inline void operator delete(void *Ptr, llvm::MCContext &C, size_t) throw () { - C.Deallocate(Ptr); + C.deallocate(Ptr); } /// This placement form of operator new[] uses the MCContext's allocator for /// obtaining memory. It is a non-throwing new[], which means that it returns /// null on error. /// Usage looks like this (assuming there's an MCContext 'Context' in scope): -/// @code -/// // Default alignment (16) +/// \code +/// // Default alignment (8) /// char *data = new (Context) char[10]; /// // Specific alignment -/// char *data = new (Context, 8) char[10]; -/// @endcode +/// char *data = new (Context, 4) char[10]; +/// \endcode /// Please note that you cannot use delete on the pointer; it must be /// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// \c Context.Deallocate(Ptr). /// -/// @param Bytes The number of bytes to allocate. Calculated by the compiler. -/// @param C The MCContext that provides the allocator. -/// @param Alignment The alignment of the allocated memory (if the underlying +/// \param Bytes The number of bytes to allocate. Calculated by the compiler. +/// \param C The MCContext that provides the allocator. +/// \param Alignment The alignment of the allocated memory (if the underlying /// allocator supports it). -/// @return The allocated memory. Could be NULL. +/// \return The allocated memory. Could be NULL. inline void *operator new[](size_t Bytes, llvm::MCContext& C, - size_t Alignment = 16) throw () { - return C.Allocate(Bytes, Alignment); + size_t Alignment = 8) throw() { + return C.allocate(Bytes, Alignment); } -/// @brief Placement delete[] companion to the new[] above. +/// \brief Placement delete[] companion to the new[] above. /// /// This operator is just a companion to the new[] above. There is no way of /// invoking it directly; see the new[] operator for more details. This operator /// is called implicitly by the compiler if a placement new[] expression using /// the MCContext throws in the object constructor. inline void operator delete[](void *Ptr, llvm::MCContext &C) throw () { - C.Deallocate(Ptr); + C.deallocate(Ptr); } #endif diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index d6b0a305b1dae..57c40d660f642 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -11,7 +11,6 @@ #include "llvm-c/Disassembler.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/DataTypes.h" @@ -61,16 +60,16 @@ public: /// Returns the disassembly of a single instruction. /// - /// @param Instr - An MCInst to populate with the contents of the + /// \param Instr - An MCInst to populate with the contents of the /// instruction. - /// @param Size - A value to populate with the size of the instruction, or + /// \param Size - A value to populate with the size of the instruction, or /// the number of bytes consumed while attempting to decode /// an invalid instruction. - /// @param Address - The address, in the memory space of region, of the first + /// \param Address - The address, in the memory space of region, of the first /// byte of the instruction. - /// @param VStream - The stream to print warnings and diagnostic messages on. - /// @param CStream - The stream to print comments and annotations on. - /// @return - MCDisassembler::Success if the instruction is valid, + /// \param VStream - The stream to print warnings and diagnostic messages on. + /// \param CStream - The stream to print comments and annotations on. + /// \return - MCDisassembler::Success if the instruction is valid, /// MCDisassembler::SoftFail if the instruction was /// disassemblable but invalid, /// MCDisassembler::Fail if the instruction was invalid. diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index c266acf2f09c5..c7bed8eccda93 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -37,34 +37,29 @@ class MCSymbol; class SourceMgr; class SMLoc; -/// MCDwarfFile - Instances of this class represent the name of the dwarf +/// \brief Instances of this class represent the name of the dwarf /// .file directive and its associated dwarf file number in the MC file, -/// and MCDwarfFile's are created and unique'd by the MCContext class where +/// and MCDwarfFile's are created and uniqued by the MCContext class where /// the file number for each is its index into the vector of DwarfFiles (note /// index 0 is not used and not a valid dwarf file number). struct MCDwarfFile { - // Name - the base name of the file without its directory path. + // \brief The base name of the file without its directory path. // The StringRef references memory allocated in the MCContext. std::string Name; - // DirIndex - the index into the list of directory names for this file name. + // \brief The index into the list of directory names for this file name. unsigned DirIndex; }; -/// MCDwarfLoc - Instances of this class represent the information from a +/// \brief Instances of this class represent the information from a /// dwarf .loc directive. class MCDwarfLoc { - // FileNum - the file number. unsigned FileNum; - // Line - the line number. unsigned Line; - // Column - the column position. unsigned Column; // Flags (see #define's below) unsigned Flags; - // Isa unsigned Isa; - // Discriminator unsigned Discriminator; // Flag that indicates the initial value of the is_stmt_start flag. @@ -87,46 +82,46 @@ private: // MCContext manages these // for an MCDwarfLoc object. public: - /// getFileNum - Get the FileNum of this MCDwarfLoc. + /// \brief Get the FileNum of this MCDwarfLoc. unsigned getFileNum() const { return FileNum; } - /// getLine - Get the Line of this MCDwarfLoc. + /// \brief Get the Line of this MCDwarfLoc. unsigned getLine() const { return Line; } - /// getColumn - Get the Column of this MCDwarfLoc. + /// \brief Get the Column of this MCDwarfLoc. unsigned getColumn() const { return Column; } - /// getFlags - Get the Flags of this MCDwarfLoc. + /// \brief Get the Flags of this MCDwarfLoc. unsigned getFlags() const { return Flags; } - /// getIsa - Get the Isa of this MCDwarfLoc. + /// \brief Get the Isa of this MCDwarfLoc. unsigned getIsa() const { return Isa; } - /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. + /// \brief Get the Discriminator of this MCDwarfLoc. unsigned getDiscriminator() const { return Discriminator; } - /// setFileNum - Set the FileNum of this MCDwarfLoc. + /// \brief Set the FileNum of this MCDwarfLoc. void setFileNum(unsigned fileNum) { FileNum = fileNum; } - /// setLine - Set the Line of this MCDwarfLoc. + /// \brief Set the Line of this MCDwarfLoc. void setLine(unsigned line) { Line = line; } - /// setColumn - Set the Column of this MCDwarfLoc. + /// \brief Set the Column of this MCDwarfLoc. void setColumn(unsigned column) { Column = column; } - /// setFlags - Set the Flags of this MCDwarfLoc. + /// \brief Set the Flags of this MCDwarfLoc. void setFlags(unsigned flags) { Flags = flags; } - /// setIsa - Set the Isa of this MCDwarfLoc. + /// \brief Set the Isa of this MCDwarfLoc. void setIsa(unsigned isa) { Isa = isa; } - /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. + /// \brief Set the Discriminator of this MCDwarfLoc. void setDiscriminator(unsigned discriminator) { Discriminator = discriminator; } }; -/// MCLineEntry - Instances of this class represent the line information for +/// \brief Instances of this class represent the line information for /// the dwarf line table entries. Which is created after a machine /// instruction is assembled and uses an address from a temporary label /// created at the current address in the current section and the info from @@ -148,24 +143,24 @@ public: // This is called when an instruction is assembled into the specified // section and if there is information from the last .loc directive that // has yet to have a line entry made for it is made. - static void Make(MCObjectStreamer *MCOS, const MCSection *Section); + static void Make(MCObjectStreamer *MCOS, MCSection *Section); }; -/// MCLineSection - Instances of this class represent the line information -/// for a compile unit where machine instructions have been assembled after seeing -/// .loc directives. This is the information used to build the dwarf line +/// \brief Instances of this class represent the line information for a compile +/// unit where machine instructions have been assembled after seeing .loc +/// directives. This is the information used to build the dwarf line /// table for a section. class MCLineSection { public: - // addLineEntry - adds an entry to this MCLineSection's line entries - void addLineEntry(const MCLineEntry &LineEntry, const MCSection *Sec) { + // \brief Add an entry to this MCLineSection's line entries. + void addLineEntry(const MCLineEntry &LineEntry, MCSection *Sec) { MCLineDivisions[Sec].push_back(LineEntry); } typedef std::vector<MCLineEntry> MCLineEntryCollection; typedef MCLineEntryCollection::iterator iterator; typedef MCLineEntryCollection::const_iterator const_iterator; - typedef MapVector<const MCSection *, MCLineEntryCollection> MCLineDivisionMap; + typedef MapVector<MCSection *, MCLineEntryCollection> MCLineDivisionMap; private: // A collection of MCLineEntry for each section. diff --git a/include/llvm/MC/MCELF.h b/include/llvm/MC/MCELF.h index 294a51bf7c765..f409988d5726c 100644 --- a/include/llvm/MC/MCELF.h +++ b/include/llvm/MC/MCELF.h @@ -15,8 +15,6 @@ #ifndef LLVM_MC_MCELF_H #define LLVM_MC_MCELF_H -#include "llvm/MC/MCExpr.h" - namespace llvm { class MCSymbolData; diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 421e7a0b2c194..cf73eca340d72 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -20,10 +20,21 @@ class MCAssembler; class MCFixup; class MCFragment; class MCObjectWriter; -class MCSectionData; class MCSymbol; class MCSymbolData; class MCValue; +class raw_pwrite_stream; + +struct ELFRelocationEntry { + uint64_t Offset; // Where is the relocation. + const MCSymbol *Symbol; // The symbol to relocate with. + unsigned Type; // The type of the relocation. + uint64_t Addend; // The addend to use. + + ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type, + uint64_t Addend) + : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {} +}; class MCELFObjectTargetWriter { const uint8_t OSABI; @@ -41,6 +52,9 @@ protected: public: static uint8_t getOSABI(Triple::OSType OSType) { switch (OSType) { + case Triple::CloudABI: + return ELF::ELFOSABI_CLOUDABI; + case Triple::PS4: case Triple::FreeBSD: return ELF::ELFOSABI_FREEBSD; case Triple::Linux: @@ -58,7 +72,10 @@ public: virtual bool needsRelocateWithSymbol(const MCSymbolData &SD, unsigned Type) const; - /// @name Accessors + virtual void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs); + + /// \name Accessors /// @{ uint8_t getOSABI() const { return OSABI; } uint16_t getEMachine() const { return EMachine; } @@ -113,7 +130,8 @@ public: /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_ostream &OS, bool IsLittleEndian); + raw_pwrite_stream &OS, + bool IsLittleEndian); } // End llvm namespace #endif diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index ab6c5e3d61240..97058f5e9981b 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -29,32 +29,26 @@ class raw_ostream; class MCELFStreamer : public MCObjectStreamer { public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter), - SeenIdent(false) {} + : MCObjectStreamer(Context, TAB, OS, Emitter), SeenIdent(false) {} - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, MCAssembler *Assembler) - : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler), - SeenIdent(false) {} - - virtual ~MCELFStreamer(); + ~MCELFStreamer() override; /// state management void reset() override { + SeenIdent = false; LocalCommons.clear(); BindingExplicitlySet.clear(); - SeenIdent = false; + BundleGroups.clear(); MCObjectStreamer::reset(); } - /// @name MCStreamer Interface + /// \name MCStreamer Interface /// @{ void InitSections(bool NoExecStack) override; - void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) override; + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; @@ -73,10 +67,10 @@ public: void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, + void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, uint64_t Size = 0, unsigned ByteAlignment = 0) override; - void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) override; + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment = 0) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()) override; @@ -95,15 +89,19 @@ public: void EmitBundleUnlock() override; private: + bool isBundleLocked() const; void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; void fixSymbolsInTLSFixups(const MCExpr *expr); + /// \brief Merge the content of the fragment \p EF into the fragment \p DF. + void mergeFragment(MCDataFragment *, MCEncodedFragmentWithFixups *); + bool SeenIdent; struct LocalCommon { - MCSymbolData *SD; + const MCSymbol *Symbol; uint64_t Size; unsigned ByteAlignment; }; @@ -111,11 +109,16 @@ private: std::vector<LocalCommon> LocalCommons; SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet; + + /// BundleGroups - The stack of fragments holding the bundle-locked + /// instructions. + llvm::SmallVector<MCDataFragment *, 4> BundleGroups; }; MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter, - bool RelaxAll, bool IsThumb); + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, bool RelaxAll, + bool IsThumb); } // end namespace llvm diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index bd9b2bc4751ab..b38ad7daee3e6 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -21,15 +21,14 @@ class MCAssembler; class MCContext; class MCFixup; class MCSection; -class MCSectionData; class MCStreamer; class MCSymbol; class MCValue; class raw_ostream; class StringRef; -typedef DenseMap<const MCSectionData*, uint64_t> SectionAddrMap; +typedef DenseMap<const MCSection *, uint64_t> SectionAddrMap; -/// MCExpr - Base class for the full range of assembler expressions which are +/// \brief Base class for the full range of assembler expressions which are /// needed for parsing. class MCExpr { public: @@ -44,8 +43,8 @@ public: private: ExprKind Kind; - MCExpr(const MCExpr&) LLVM_DELETED_FUNCTION; - void operator=(const MCExpr&) LLVM_DELETED_FUNCTION; + MCExpr(const MCExpr&) = delete; + void operator=(const MCExpr&) = delete; bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, @@ -56,53 +55,52 @@ private: const SectionAddrMap *Addrs, bool InSet) const; protected: - explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {} + explicit MCExpr(ExprKind Kind) : Kind(Kind) {} bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const MCFixup *Fixup, - const SectionAddrMap *Addrs, bool InSet, - bool ForceVarExpansion) const; + const SectionAddrMap *Addrs, bool InSet) const; public: - /// @name Accessors + /// \name Accessors /// @{ ExprKind getKind() const { return Kind; } /// @} - /// @name Utility Methods + /// \name Utility Methods /// @{ void print(raw_ostream &OS) const; void dump() const; /// @} - /// @name Expression Evaluation + /// \name Expression Evaluation /// @{ - /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value. + /// \brief Try to evaluate the expression to an absolute value. /// - /// @param Res - The absolute value, if evaluation succeeds. - /// @param Layout - The assembler layout object to use for evaluating symbol + /// \param Res - The absolute value, if evaluation succeeds. + /// \param Layout - The assembler layout object to use for evaluating symbol /// values. If not given, then only non-symbolic expressions will be /// evaluated. - /// @result - True on success. + /// \return - True on success. bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, const SectionAddrMap &Addrs) const; bool EvaluateAsAbsolute(int64_t &Res) const; bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; - int64_t evaluateKnownAbsolute(const MCAsmLayout &Layout) const; + bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; - /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable - /// value, i.e. an expression of the fixed form (a - b + constant). + /// \brief Try to evaluate the expression to a relocatable value, i.e. an + /// expression of the fixed form (a - b + constant). /// - /// @param Res - The relocatable value, if evaluation succeeds. - /// @param Layout - The assembler layout object to use for evaluating values. - /// @param Fixup - The Fixup object if available. - /// @result - True on success. + /// \param Res - The relocatable value, if evaluation succeeds. + /// \param Layout - The assembler layout object to use for evaluating values. + /// \param Fixup - The Fixup object if available. + /// \return - True on success. bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const; @@ -110,16 +108,14 @@ public: /// neither a nor b are variables. /// /// This is a more aggressive variant of EvaluateAsRelocatable. The intended - /// use is for when relocations are not available, like the symbol value in - /// the symbol table. - bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout, - const MCFixup *Fixup) const; + /// use is for when relocations are not available, like the .size directive. + bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const; - /// FindAssociatedSection - Find the "associated section" for this expression, - /// which is currently defined as the absolute section for constants, or + /// \brief Find the "associated section" for this expression, which is + /// currently defined as the absolute section for constants, or /// otherwise the section associated with the first defined symbol in the /// expression. - const MCSection *FindAssociatedSection() const; + MCSection *FindAssociatedSection() const; /// @} }; @@ -129,21 +125,21 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { return OS; } -//// MCConstantExpr - Represent a constant integer expression. +//// \brief Represent a constant integer expression. class MCConstantExpr : public MCExpr { int64_t Value; - explicit MCConstantExpr(int64_t _Value) - : MCExpr(MCExpr::Constant), Value(_Value) {} + explicit MCConstantExpr(int64_t Value) + : MCExpr(MCExpr::Constant), Value(Value) {} public: - /// @name Construction + /// \name Construction /// @{ static const MCConstantExpr *Create(int64_t Value, MCContext &Ctx); /// @} - /// @name Accessors + /// \name Accessors /// @{ int64_t getValue() const { return Value; } @@ -155,15 +151,14 @@ public: } }; -/// MCSymbolRefExpr - Represent a reference to a symbol from inside an -/// expression. +/// \brief Represent a reference to a symbol from inside an expression. /// /// A symbol reference in an expression may be a use of a label, a use of an /// assembler variable (defined constant), or constitute an implicit definition /// of the symbol as external. class MCSymbolRefExpr : public MCExpr { public: - enum VariantKind { + enum VariantKind : uint16_t { VK_None, VK_Invalid, @@ -188,6 +183,7 @@ public: VK_GOTPAGE, VK_GOTPAGEOFF, VK_SECREL, + VK_SIZE, // symbol@SIZE VK_WEAKREF, // The link between the symbols in .weakref foo, bar VK_ARM_NONE, @@ -280,12 +276,25 @@ public: VK_Mips_PCREL_HI16, VK_Mips_PCREL_LO16, - VK_COFF_IMGREL32 // symbol@imgrel (image-relative) + VK_COFF_IMGREL32, // symbol@imgrel (image-relative) + + VK_Hexagon_PCREL, + VK_Hexagon_LO16, + VK_Hexagon_HI16, + VK_Hexagon_GPREL, + VK_Hexagon_GD_GOT, + VK_Hexagon_LD_GOT, + VK_Hexagon_GD_PLT, + VK_Hexagon_LD_PLT, + VK_Hexagon_IE, + VK_Hexagon_IE_GOT, + VK_TPREL, + VK_DTPREL }; private: /// The symbol reference modifier. - const unsigned Kind : 16; + const VariantKind Kind; /// Specifies how the variant kind should be printed. const unsigned UseParensForSymbolVariant : 1; @@ -300,7 +309,7 @@ private: const MCAsmInfo *MAI); public: - /// @name Construction + /// \name Construction /// @{ static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx) { @@ -313,19 +322,19 @@ public: MCContext &Ctx); /// @} - /// @name Accessors + /// \name Accessors /// @{ const MCSymbol &getSymbol() const { return *Symbol; } - VariantKind getKind() const { return static_cast<VariantKind>(Kind); } + VariantKind getKind() const { return Kind; } void printVariantKind(raw_ostream &OS) const; bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } /// @} - /// @name Static Utility Functions + /// \name Static Utility Functions /// @{ static StringRef getVariantKindName(VariantKind Kind); @@ -339,7 +348,7 @@ public: } }; -/// MCUnaryExpr - Unary assembler expressions. +/// \brief Unary assembler expressions. class MCUnaryExpr : public MCExpr { public: enum Opcode { @@ -353,11 +362,11 @@ private: Opcode Op; const MCExpr *Expr; - MCUnaryExpr(Opcode _Op, const MCExpr *_Expr) - : MCExpr(MCExpr::Unary), Op(_Op), Expr(_Expr) {} + MCUnaryExpr(Opcode Op, const MCExpr *Expr) + : MCExpr(MCExpr::Unary), Op(Op), Expr(Expr) {} public: - /// @name Construction + /// \name Construction /// @{ static const MCUnaryExpr *Create(Opcode Op, const MCExpr *Expr, @@ -376,13 +385,13 @@ public: } /// @} - /// @name Accessors + /// \name Accessors /// @{ - /// getOpcode - Get the kind of this unary expression. + /// \brief Get the kind of this unary expression. Opcode getOpcode() const { return Op; } - /// getSubExpr - Get the child of this unary expression. + /// \brief Get the child of this unary expression. const MCExpr *getSubExpr() const { return Expr; } /// @} @@ -392,7 +401,7 @@ public: } }; -/// MCBinaryExpr - Binary assembler expressions. +/// \brief Binary assembler expressions. class MCBinaryExpr : public MCExpr { public: enum Opcode { @@ -415,7 +424,8 @@ public: NE, ///< Inequality comparison. Or, ///< Bitwise or. Shl, ///< Shift left. - Shr, ///< Shift right (arithmetic or logical, depending on target) + AShr, ///< Arithmetic shift right. + LShr, ///< Logical shift right. Sub, ///< Subtraction. Xor ///< Bitwise exclusive or. }; @@ -424,11 +434,11 @@ private: Opcode Op; const MCExpr *LHS, *RHS; - MCBinaryExpr(Opcode _Op, const MCExpr *_LHS, const MCExpr *_RHS) - : MCExpr(MCExpr::Binary), Op(_Op), LHS(_LHS), RHS(_RHS) {} + MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS) + : MCExpr(MCExpr::Binary), Op(Op), LHS(LHS), RHS(RHS) {} public: - /// @name Construction + /// \name Construction /// @{ static const MCBinaryExpr *Create(Opcode Op, const MCExpr *LHS, @@ -493,9 +503,13 @@ public: MCContext &Ctx) { return Create(Shl, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateShr(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *CreateAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Shr, LHS, RHS, Ctx); + return Create(AShr, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLShr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LShr, LHS, RHS, Ctx); } static const MCBinaryExpr *CreateSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { @@ -507,16 +521,16 @@ public: } /// @} - /// @name Accessors + /// \name Accessors /// @{ - /// getOpcode - Get the kind of this binary expression. + /// \brief Get the kind of this binary expression. Opcode getOpcode() const { return Op; } - /// getLHS - Get the left-hand side expression of the binary operator. + /// \brief Get the left-hand side expression of the binary operator. const MCExpr *getLHS() const { return LHS; } - /// getRHS - Get the right-hand side expression of the binary operator. + /// \brief Get the right-hand side expression of the binary operator. const MCExpr *getRHS() const { return RHS; } /// @} @@ -526,8 +540,8 @@ public: } }; -/// MCTargetExpr - This is an extension point for target-specific MCExpr -/// subclasses to implement. +/// \brief This is an extension point for target-specific MCExpr subclasses to +/// implement. /// /// NOTE: All subclasses are required to have trivial destructors because /// MCExprs are bump pointer allocated and not destructed. @@ -543,7 +557,7 @@ public: const MCAsmLayout *Layout, const MCFixup *Fixup) const = 0; virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; - virtual const MCSection *FindAssociatedSection() const = 0; + virtual MCSection *FindAssociatedSection() const = 0; virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index 98a1419a1934a..8ab477c401a1c 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -19,7 +19,7 @@ namespace llvm { class MCExpr; -/// MCFixupKind - Extensible enumeration to represent the type of a fixup. +/// \brief Extensible enumeration to represent the type of a fixup. enum MCFixupKind { FK_Data_1 = 0, ///< A one-byte fixup. FK_Data_2, ///< A two-byte fixup. @@ -45,7 +45,7 @@ enum MCFixupKind { MaxTargetFixupKind = (1 << 8) }; -/// MCFixup - Encode information on a single operation to perform on a byte +/// \brief Encode information on a single operation to perform on a byte /// sequence (e.g., an encoded instruction) which requires assemble- or run- /// time patching. /// @@ -75,7 +75,7 @@ class MCFixup { /// The source location which gave rise to the fixup, if any. SMLoc Loc; public: - static MCFixup Create(uint32_t Offset, const MCExpr *Value, + static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc = SMLoc()) { assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!"); MCFixup FI; @@ -93,8 +93,8 @@ public: const MCExpr *getValue() const { return Value; } - /// getKindForSize - Return the generic fixup kind for a value with the given - /// size. It is an error to pass an unsupported size. + /// \brief Return the generic fixup kind for a value with the given size. It + /// is an error to pass an unsupported size. static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) { switch (Size) { default: llvm_unreachable("Invalid generic fixup size!"); diff --git a/include/llvm/MC/MCFixupKindInfo.h b/include/llvm/MC/MCFixupKindInfo.h index 6979ad5807d03..58183bd778e63 100644 --- a/include/llvm/MC/MCFixupKindInfo.h +++ b/include/llvm/MC/MCFixupKindInfo.h @@ -12,7 +12,7 @@ namespace llvm { -/// MCFixupKindInfo - Target independent information on a fixup kind. +/// \brief Target independent information on a fixup kind. struct MCFixupKindInfo { enum FixupKindFlags { /// Is this fixup kind PCrelative? This is used by the assembler backend to diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 25cd5ccb08fd6..2fc5091484039 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -28,7 +28,7 @@ class MCInstPrinter; class MCExpr; class MCInst; -/// MCOperand - Instances of this class represent operands of the MCInst class. +/// \brief Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. class MCOperand { enum MachineOperandType : unsigned char { @@ -59,13 +59,13 @@ public: bool isExpr() const { return Kind == kExpr; } bool isInst() const { return Kind == kInst; } - /// getReg - Returns the register number. + /// \brief Returns the register number. unsigned getReg() const { assert(isReg() && "This is not a register operand!"); return RegVal; } - /// setReg - Set the register number. + /// \brief Set the register number. void setReg(unsigned Reg) { assert(isReg() && "This is not a register operand!"); RegVal = Reg; @@ -108,44 +108,44 @@ public: InstVal = Val; } - static MCOperand CreateReg(unsigned Reg) { + static MCOperand createReg(unsigned Reg) { MCOperand Op; Op.Kind = kRegister; Op.RegVal = Reg; return Op; } - static MCOperand CreateImm(int64_t Val) { + static MCOperand createImm(int64_t Val) { MCOperand Op; Op.Kind = kImmediate; Op.ImmVal = Val; return Op; } - static MCOperand CreateFPImm(double Val) { + static MCOperand createFPImm(double Val) { MCOperand Op; Op.Kind = kFPImmediate; Op.FPImmVal = Val; return Op; } - static MCOperand CreateExpr(const MCExpr *Val) { + static MCOperand createExpr(const MCExpr *Val) { MCOperand Op; Op.Kind = kExpr; Op.ExprVal = Val; return Op; } - static MCOperand CreateInst(const MCInst *Val) { + static MCOperand createInst(const MCInst *Val) { MCOperand Op; Op.Kind = kInst; Op.InstVal = Val; return Op; } - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; }; template <> struct isPodLike<MCOperand> { static const bool value = true; }; -/// MCInst - Instances of this class represent a single low-level machine +/// \brief Instances of this class represent a single low-level machine /// instruction. class MCInst { unsigned Opcode; @@ -169,7 +169,7 @@ public: } void clear() { Operands.clear(); } - size_t size() { return Operands.size(); } + size_t size() const { return Operands.size(); } typedef SmallVectorImpl<MCOperand>::iterator iterator; typedef SmallVectorImpl<MCOperand>::const_iterator const_iterator; @@ -181,24 +181,23 @@ public: return Operands.insert(I, Op); } - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; /// \brief Dump the MCInst as prettily as possible using the additional MC /// structures, if given. Operators are separated by the \p Separator /// string. - void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = nullptr, - const MCInstPrinter *Printer = nullptr, + void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr, StringRef Separator = " ") const; }; inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { - MO.print(OS, nullptr); + MO.print(OS); return OS; } inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { - MI.print(OS, nullptr); + MI.print(OS); return OS; } diff --git a/include/llvm/MC/MCInstBuilder.h b/include/llvm/MC/MCInstBuilder.h index c5acb26eecac3..30609bdb8b27a 100644 --- a/include/llvm/MC/MCInstBuilder.h +++ b/include/llvm/MC/MCInstBuilder.h @@ -30,31 +30,37 @@ public: /// \brief Add a new register operand. MCInstBuilder &addReg(unsigned Reg) { - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return *this; } /// \brief Add a new integer immediate operand. MCInstBuilder &addImm(int64_t Val) { - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createImm(Val)); return *this; } /// \brief Add a new floating point immediate operand. MCInstBuilder &addFPImm(double Val) { - Inst.addOperand(MCOperand::CreateFPImm(Val)); + Inst.addOperand(MCOperand::createFPImm(Val)); return *this; } /// \brief Add a new MCExpr operand. MCInstBuilder &addExpr(const MCExpr *Val) { - Inst.addOperand(MCOperand::CreateExpr(Val)); + Inst.addOperand(MCOperand::createExpr(Val)); return *this; } /// \brief Add a new MCInst operand. MCInstBuilder &addInst(const MCInst *Val) { - Inst.addOperand(MCOperand::CreateInst(Val)); + Inst.addOperand(MCOperand::createInst(Val)); + return *this; + } + + /// \brief Add an operand. + MCInstBuilder &addOperand(const MCOperand &Op) { + Inst.addOperand(Op); return *this; } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 95124c3021dd2..7e8563a195d0f 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -19,6 +19,7 @@ class raw_ostream; class MCAsmInfo; class MCInstrInfo; class MCRegisterInfo; +class MCSubtargetInfo; class StringRef; namespace HexStyle { @@ -28,21 +29,18 @@ namespace HexStyle { }; } -/// MCInstPrinter - This is an instance of a target assembly language printer -/// that converts an MCInst to valid target assembly syntax. +/// \brief This is an instance of a target assembly language printer that +/// converts an MCInst to valid target assembly syntax. class MCInstPrinter { protected: - /// CommentStream - a stream that comments can be emitted to if desired. - /// Each comment must end with a newline. This will be null if verbose - /// assembly emission is disable. + /// \brief A stream that comments can be emitted to if desired. Each comment + /// must end with a newline. This will be null if verbose assembly emission + /// is disable. raw_ostream *CommentStream; const MCAsmInfo &MAI; const MCInstrInfo &MII; const MCRegisterInfo &MRI; - /// The current set of available features. - uint64_t AvailableFeatures; - /// True if we are printing marked up assembly. bool UseMarkup; @@ -58,29 +56,25 @@ public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) : CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), - AvailableFeatures(0), UseMarkup(0), PrintImmHex(0), + UseMarkup(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); - /// setCommentStream - Specify a stream to emit comments to. + /// \brief Specify a stream to emit comments to. void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } - /// printInst - Print the specified MCInst to the specified raw_ostream. - /// + /// \brief Print the specified MCInst to the specified raw_ostream. virtual void printInst(const MCInst *MI, raw_ostream &OS, - StringRef Annot) = 0; + StringRef Annot, const MCSubtargetInfo &STI) = 0; - /// getOpcodeName - Return the name of the specified opcode enum (e.g. - /// "MOV32ri") or empty if we can't resolve it. + /// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or + /// empty if we can't resolve it. StringRef getOpcodeName(unsigned Opcode) const; - /// printRegName - Print the assembler register name. + /// \brief Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - uint64_t getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } - bool getUseMarkup() const { return UseMarkup; } void setUseMarkup(bool Value) { UseMarkup = Value; } @@ -95,12 +89,14 @@ public: void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } /// Utility function to print immediates in decimal or hex. - format_object1<int64_t> formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); } + format_object<int64_t> formatImm(int64_t Value) const { + return PrintImmHex ? formatHex(Value) : formatDec(Value); + } /// Utility functions to print decimal/hexadecimal values. - format_object1<int64_t> formatDec(const int64_t Value) const; - format_object1<int64_t> formatHex(const int64_t Value) const; - format_object1<uint64_t> formatHex(const uint64_t Value) const; + format_object<int64_t> formatDec(int64_t Value) const; + format_object<int64_t> formatHex(int64_t Value) const; + format_object<uint64_t> formatHex(uint64_t Value) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index e921f768ac45f..8f5159e9e1c85 100644 --- a/include/llvm/MC/MCInstrAnalysis.h +++ b/include/llvm/MC/MCInstrAnalysis.h @@ -59,8 +59,8 @@ public: return Info->get(Inst.getOpcode()).isTerminator(); } - /// evaluateBranch - Given a branch instruction try to get the address the - /// branch targets. Return true on success, and the address in Target. + /// \brief Given a branch instruction try to get the address the branch + /// targets. Return true on success, and the address in Target. virtual bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, uint64_t &Target) const; diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 360989305d3af..de3a1959e05c9 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -15,142 +15,142 @@ #ifndef LLVM_MC_MCINSTRDESC_H #define LLVM_MC_MCINSTRDESC_H -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/DataTypes.h" +#include <string> namespace llvm { + class MCInst; + class MCRegisterInfo; + class MCSubtargetInfo; + class FeatureBitset; //===----------------------------------------------------------------------===// // Machine Operand Flags and Description //===----------------------------------------------------------------------===// namespace MCOI { - // Operand constraints - enum OperandConstraint { - TIED_TO = 0, // Must be allocated the same register as. - EARLY_CLOBBER // Operand is an early clobber register operand - }; - - /// OperandFlags - These are flags set on operands, but should be considered - /// private, all access should go through the MCOperandInfo accessors. - /// See the accessors for a description of what these are. - enum OperandFlags { - LookupPtrRegClass = 0, - Predicate, - OptionalDef - }; - - /// Operand Type - Operands are tagged with one of the values of this enum. - enum OperandType { - OPERAND_UNKNOWN = 0, - OPERAND_IMMEDIATE = 1, - OPERAND_REGISTER = 2, - OPERAND_MEMORY = 3, - OPERAND_PCREL = 4, - OPERAND_FIRST_TARGET = 5 - }; +// Operand constraints +enum OperandConstraint { + TIED_TO = 0, // Must be allocated the same register as. + EARLY_CLOBBER // Operand is an early clobber register operand +}; + +/// \brief These are flags set on operands, but should be considered +/// private, all access should go through the MCOperandInfo accessors. +/// See the accessors for a description of what these are. +enum OperandFlags { LookupPtrRegClass = 0, Predicate, OptionalDef }; + +/// \brief Operands are tagged with one of the values of this enum. +enum OperandType { + OPERAND_UNKNOWN = 0, + OPERAND_IMMEDIATE = 1, + OPERAND_REGISTER = 2, + OPERAND_MEMORY = 3, + OPERAND_PCREL = 4, + OPERAND_FIRST_TARGET = 5 +}; } -/// MCOperandInfo - This holds information about one operand of a machine -/// instruction, indicating the register class for register operands, etc. -/// +/// \brief This holds information about one operand of a machine instruction, +/// indicating the register class for register operands, etc. class MCOperandInfo { public: - /// RegClass - This specifies the register class enumeration of the operand + /// \brief This specifies the register class enumeration of the operand /// if the operand is a register. If isLookupPtrRegClass is set, then this is /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to /// get a dynamic register class. int16_t RegClass; - /// Flags - These are flags from the MCOI::OperandFlags enum. + /// \brief These are flags from the MCOI::OperandFlags enum. uint8_t Flags; - /// OperandType - Information about the type of the operand. + /// \brief Information about the type of the operand. uint8_t OperandType; - - /// Lower 16 bits are used to specify which constraints are set. The higher 16 - /// bits are used to specify the value of constraints (4 bits each). + /// \brief The lower 16 bits are used to specify which constraints are set. + /// The higher 16 bits are used to specify the value of constraints (4 bits + /// each). uint32_t Constraints; - /// Currently no other information. - /// isLookupPtrRegClass - Set if this operand is a pointer value and it - /// requires a callback to look up its register class. - bool isLookupPtrRegClass() const {return Flags&(1 <<MCOI::LookupPtrRegClass);} + /// \brief Set if this operand is a pointer value and it requires a callback + /// to look up its register class. + bool isLookupPtrRegClass() const { + return Flags & (1 << MCOI::LookupPtrRegClass); + } - /// isPredicate - Set if this is one of the operands that made up of - /// the predicate operand that controls an isPredicable() instruction. + /// \brief Set if this is one of the operands that made up of the predicate + /// operand that controls an isPredicable() instruction. bool isPredicate() const { return Flags & (1 << MCOI::Predicate); } - /// isOptionalDef - Set if this operand is a optional def. - /// + /// \brief Set if this operand is a optional def. bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); } }; - //===----------------------------------------------------------------------===// // Machine Instruction Flags and Description //===----------------------------------------------------------------------===// -/// MCInstrDesc flags - These should be considered private to the -/// implementation of the MCInstrDesc class. Clients should use the predicate -/// methods on MCInstrDesc, not use these directly. These all correspond to -/// bitfields in the MCInstrDesc::Flags field. namespace MCID { - enum { - Variadic = 0, - HasOptionalDef, - Pseudo, - Return, - Call, - Barrier, - Terminator, - Branch, - IndirectBranch, - Compare, - MoveImm, - Bitcast, - Select, - DelaySlot, - FoldableAsLoad, - MayLoad, - MayStore, - Predicable, - NotDuplicable, - UnmodeledSideEffects, - Commutable, - ConvertibleTo3Addr, - UsesCustomInserter, - HasPostISelHook, - Rematerializable, - CheapAsAMove, - ExtraSrcRegAllocReq, - ExtraDefRegAllocReq, - RegSequence, - ExtractSubreg, - InsertSubreg - }; +/// \brief These should be considered private to the implementation of the +/// MCInstrDesc class. Clients should use the predicate methods on MCInstrDesc, +/// not use these directly. These all correspond to bitfields in the +/// MCInstrDesc::Flags field. +enum Flag { + Variadic = 0, + HasOptionalDef, + Pseudo, + Return, + Call, + Barrier, + Terminator, + Branch, + IndirectBranch, + Compare, + MoveImm, + Bitcast, + Select, + DelaySlot, + FoldableAsLoad, + MayLoad, + MayStore, + Predicable, + NotDuplicable, + UnmodeledSideEffects, + Commutable, + ConvertibleTo3Addr, + UsesCustomInserter, + HasPostISelHook, + Rematerializable, + CheapAsAMove, + ExtraSrcRegAllocReq, + ExtraDefRegAllocReq, + RegSequence, + ExtractSubreg, + InsertSubreg +}; } -/// MCInstrDesc - Describe properties that are true of each instruction in the -/// target description file. This captures information about side effects, -/// register use and many other things. There is one instance of this struct -/// for each target instruction class, and the MachineInstr class points to -/// this struct directly to describe itself. +/// \brief Describe properties that are true of each instruction in the target +/// description file. This captures information about side effects, register +/// use and many other things. There is one instance of this struct for each +/// target instruction class, and the MachineInstr class points to this struct +/// directly to describe itself. class MCInstrDesc { public: - unsigned short Opcode; // The opcode number - unsigned short NumOperands; // Num of args (may be more if variable_ops) - unsigned short NumDefs; // Num of args that are definitions - unsigned short SchedClass; // enum identifying instr sched class - unsigned short Size; // Number of bytes in encoding. - unsigned Flags; // Flags identifying machine instr class - uint64_t TSFlags; // Target Specific Flag values - const uint16_t *ImplicitUses; // Registers implicitly read by this instr - const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr - const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands - uint64_t DeprecatedFeatureMask;// Feature bits that this is deprecated on, if any + unsigned short Opcode; // The opcode number + unsigned short NumOperands; // Num of args (may be more if variable_ops) + unsigned short NumDefs; // Num of args that are definitions + unsigned short SchedClass; // enum identifying instr sched class + unsigned short Size; // Number of bytes in encoding. + unsigned Flags; // Flags identifying machine instr class + uint64_t TSFlags; // Target Specific Flag values + const uint16_t *ImplicitUses; // Registers implicitly read by this instr + const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr + const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands + // Subtarget feature that this is deprecated on, if any + // -1 implies this is not deprecated by any single feature. It may still be + // deprecated due to a "complex" reason, below. + int64_t DeprecatedFeature; + // A complex method to determine is a certain is deprecated or not, and return // the reason for deprecation. bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &); @@ -170,38 +170,23 @@ public: /// \brief Returns true if a certain instruction is deprecated and if so /// returns the reason in \p Info. bool getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI, - std::string &Info) const { - if (ComplexDeprecationInfo) - return ComplexDeprecationInfo(MI, STI, Info); - if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) { - // FIXME: it would be nice to include the subtarget feature here. - Info = "deprecated"; - return true; - } - return false; - } + std::string &Info) const; /// \brief Return the opcode number for this descriptor. - unsigned getOpcode() const { - return Opcode; - } + unsigned getOpcode() const { return Opcode; } /// \brief Return the number of declared MachineOperands for this /// MachineInstruction. Note that variadic (isVariadic() returns true) /// instructions may have additional operands at the end of the list, and note /// that the machine instruction may include implicit register def/uses as /// well. - unsigned getNumOperands() const { - return NumOperands; - } + unsigned getNumOperands() const { return NumOperands; } /// \brief Return the number of MachineOperands that are register /// definitions. Register definitions always occur at the start of the /// machine operand list. This is the number of "outs" in the .td file, /// and does not include implicit defs. - unsigned getNumDefs() const { - return NumDefs; - } + unsigned getNumDefs() const { return NumDefs; } /// \brief Return flags of this instruction. unsigned getFlags() const { return Flags; } @@ -210,39 +195,26 @@ public: /// operands. In this case, the variable operands will be after the normal /// operands but before the implicit definitions and uses (if any are /// present). - bool isVariadic() const { - return Flags & (1 << MCID::Variadic); - } + bool isVariadic() const { return Flags & (1 << MCID::Variadic); } /// \brief Set if this instruction has an optional definition, e.g. /// ARM instructions which can set condition code if 's' bit is set. - bool hasOptionalDef() const { - return Flags & (1 << MCID::HasOptionalDef); - } + bool hasOptionalDef() const { return Flags & (1 << MCID::HasOptionalDef); } /// \brief Return true if this is a pseudo instruction that doesn't /// correspond to a real machine instruction. - /// - bool isPseudo() const { - return Flags & (1 << MCID::Pseudo); - } + bool isPseudo() const { return Flags & (1 << MCID::Pseudo); } /// \brief Return true if the instruction is a return. - bool isReturn() const { - return Flags & (1 << MCID::Return); - } + bool isReturn() const { return Flags & (1 << MCID::Return); } /// \brief Return true if the instruction is a call. - bool isCall() const { - return Flags & (1 << MCID::Call); - } + bool isCall() const { return Flags & (1 << MCID::Call); } /// \brief Returns true if the specified instruction stops control flow /// from executing the instruction immediately following it. Examples include /// unconditional branches and return instructions. - bool isBarrier() const { - return Flags & (1 << MCID::Barrier); - } + bool isBarrier() const { return Flags & (1 << MCID::Barrier); } /// \brief Returns true if this instruction part of the terminator for /// a basic block. Typically this is things like return and branch @@ -250,23 +222,17 @@ public: /// /// Various passes use this to insert code into the bottom of a basic block, /// but before control flow occurs. - bool isTerminator() const { - return Flags & (1 << MCID::Terminator); - } + bool isTerminator() const { return Flags & (1 << MCID::Terminator); } /// \brief Returns true if this is a conditional, unconditional, or /// indirect branch. Predicates below can be used to discriminate between /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to /// get more information. - bool isBranch() const { - return Flags & (1 << MCID::Branch); - } + bool isBranch() const { return Flags & (1 << MCID::Branch); } /// \brief Return true if this is an indirect branch, such as a /// branch through a register. - bool isIndirectBranch() const { - return Flags & (1 << MCID::IndirectBranch); - } + bool isIndirectBranch() const { return Flags & (1 << MCID::IndirectBranch); } /// \brief Return true if this is a branch which may fall /// through to the next instruction or may transfer control flow to some other @@ -287,79 +253,44 @@ public: /// \brief Return true if this is a branch or an instruction which directly /// writes to the program counter. Considered 'may' affect rather than /// 'does' affect as things like predication are not taken into account. - bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const { - if (isBranch() || isCall() || isReturn() || isIndirectBranch()) - return true; - unsigned PC = RI.getProgramCounter(); - if (PC == 0) - return false; - if (hasDefOfPhysReg(MI, PC, RI)) - return true; - // A variadic instruction may define PC in the variable operand list. - // There's currently no indication of which entries in a variable - // list are defs and which are uses. While that's the case, this function - // needs to assume they're defs in order to be conservatively correct. - for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) { - if (MI.getOperand(i).isReg() && - RI.isSubRegisterEq(PC, MI.getOperand(i).getReg())) - return true; - } - return false; - } + bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const; /// \brief Return true if this instruction has a predicate operand /// that controls execution. It may be set to 'always', or may be set to other /// values. There are various methods in TargetInstrInfo that can be used to /// control and modify the predicate in this instruction. - bool isPredicable() const { - return Flags & (1 << MCID::Predicable); - } + bool isPredicable() const { return Flags & (1 << MCID::Predicable); } /// \brief Return true if this instruction is a comparison. - bool isCompare() const { - return Flags & (1 << MCID::Compare); - } + bool isCompare() const { return Flags & (1 << MCID::Compare); } /// \brief Return true if this instruction is a move immediate /// (including conditional moves) instruction. - bool isMoveImmediate() const { - return Flags & (1 << MCID::MoveImm); - } + bool isMoveImmediate() const { return Flags & (1 << MCID::MoveImm); } /// \brief Return true if this instruction is a bitcast instruction. - bool isBitcast() const { - return Flags & (1 << MCID::Bitcast); - } + bool isBitcast() const { return Flags & (1 << MCID::Bitcast); } /// \brief Return true if this is a select instruction. - bool isSelect() const { - return Flags & (1 << MCID::Select); - } + bool isSelect() const { return Flags & (1 << MCID::Select); } /// \brief Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. - bool isNotDuplicable() const { - return Flags & (1 << MCID::NotDuplicable); - } + bool isNotDuplicable() const { return Flags & (1 << MCID::NotDuplicable); } - /// hasDelaySlot - Returns true if the specified instruction has a delay slot - /// which must be filled by the code generator. - bool hasDelaySlot() const { - return Flags & (1 << MCID::DelaySlot); - } + /// \brief Returns true if the specified instruction has a delay slot which + /// must be filled by the code generator. + bool hasDelaySlot() const { return Flags & (1 << MCID::DelaySlot); } - /// canFoldAsLoad - Return true for instructions that can be folded as - /// memory operands in other instructions. The most common use for this - /// is instructions that are simple loads from memory that don't modify - /// the loaded value in any way, but it can also be used for instructions - /// that can be expressed as constant-pool loads, such as V_SETALLONES - /// on x86, to allow them to be folded when it is beneficial. - /// This should only be set on instructions that return a value in their - /// only virtual register definition. - bool canFoldAsLoad() const { - return Flags & (1 << MCID::FoldableAsLoad); - } + /// \brief Return true for instructions that can be folded as memory operands + /// in other instructions. The most common use for this is instructions that + /// are simple loads from memory that don't modify the loaded value in any + /// way, but it can also be used for instructions that can be expressed as + /// constant-pool loads, such as V_SETALLONES on x86, to allow them to be + /// folded when it is beneficial. This should only be set on instructions + /// that return a value in their only virtual register definition. + bool canFoldAsLoad() const { return Flags & (1 << MCID::FoldableAsLoad); } /// \brief Return true if this instruction behaves /// the same way as the generic REG_SEQUENCE instructions. @@ -398,9 +329,7 @@ public: /// Note that for the optimizers to be able to take advantage of /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be /// override accordingly. - bool isInsertSubregLike() const { - return Flags & (1 << MCID::InsertSubreg); - } + bool isInsertSubregLike() const { return Flags & (1 << MCID::InsertSubreg); } //===--------------------------------------------------------------------===// // Side Effect Analysis @@ -409,20 +338,15 @@ public: /// \brief Return true if this instruction could possibly read memory. /// Instructions with this flag set are not necessarily simple load /// instructions, they may load a value and modify it, for example. - bool mayLoad() const { - return Flags & (1 << MCID::MayLoad); - } - + bool mayLoad() const { return Flags & (1 << MCID::MayLoad); } /// \brief Return true if this instruction could possibly modify memory. /// Instructions with this flag set are not necessarily simple store /// instructions, they may store a modified value based on their operands, or /// may not actually modify anything, for example. - bool mayStore() const { - return Flags & (1 << MCID::MayStore); - } + bool mayStore() const { return Flags & (1 << MCID::MayStore); } - /// hasUnmodeledSideEffects - Return true if this instruction has side + /// \brief Return true if this instruction has side /// effects that are not modeled by other flags. This does not return true /// for instructions whose effects are captured by: /// @@ -434,7 +358,6 @@ public: /// Examples of side effects would be modifying 'invisible' machine state like /// a control register, flushing a cache, modifying a register invisible to /// LLVM, etc. - /// bool hasUnmodeledSideEffects() const { return Flags & (1 << MCID::UnmodeledSideEffects); } @@ -443,9 +366,9 @@ public: // Flags that indicate whether an instruction can be modified by a method. //===--------------------------------------------------------------------===// - /// isCommutable - Return true if this may be a 2- or 3-address - /// instruction (of the form "X = op Y, Z, ..."), which produces the same - /// result if Y and Z are exchanged. If this flag is set, then the + /// \brief Return true if this may be a 2- or 3-address instruction (of the + /// form "X = op Y, Z, ..."), which produces the same result if Y and Z are + /// exchanged. If this flag is set, then the /// TargetInstrInfo::commuteInstruction method may be used to hack on the /// instruction. /// @@ -453,18 +376,16 @@ public: /// sometimes. In these cases, the call to commuteInstruction will fail. /// Also note that some instructions require non-trivial modification to /// commute them. - bool isCommutable() const { - return Flags & (1 << MCID::Commutable); - } - - /// isConvertibleTo3Addr - Return true if this is a 2-address instruction - /// which can be changed into a 3-address instruction if needed. Doing this - /// transformation can be profitable in the register allocator, because it - /// means that the instruction can use a 2-address form if possible, but - /// degrade into a less efficient form if the source and dest register cannot - /// be assigned to the same register. For example, this allows the x86 - /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which - /// is the same speed as the shift but has bigger code size. + bool isCommutable() const { return Flags & (1 << MCID::Commutable); } + + /// \brief Return true if this is a 2-address instruction which can be changed + /// into a 3-address instruction if needed. Doing this transformation can be + /// profitable in the register allocator, because it means that the + /// instruction can use a 2-address form if possible, but degrade into a less + /// efficient form if the source and dest register cannot be assigned to the + /// same register. For example, this allows the x86 backend to turn a "shl + /// reg, 3" instruction into an LEA instruction, which is the same speed as + /// the shift but has bigger code size. /// /// If this returns true, then the target must implement the /// TargetInstrInfo::convertToThreeAddress method for this instruction, which @@ -475,11 +396,11 @@ public: return Flags & (1 << MCID::ConvertibleTo3Addr); } - /// usesCustomInsertionHook - Return true if this instruction requires - /// custom insertion support when the DAG scheduler is inserting it into a - /// machine basic block. If this is true for the instruction, it basically - /// means that it is a pseudo instruction used at SelectionDAG time that is - /// expanded out into magic code by the target when MachineInstrs are formed. + /// \brief Return true if this instruction requires custom insertion support + /// when the DAG scheduler is inserting it into a machine basic block. If + /// this is true for the instruction, it basically means that it is a pseudo + /// instruction used at SelectionDAG time that is expanded out into magic code + /// by the target when MachineInstrs are formed. /// /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method /// is used to insert this into the MachineBasicBlock. @@ -487,17 +408,14 @@ public: return Flags & (1 << MCID::UsesCustomInserter); } - /// hasPostISelHook - Return true if this instruction requires *adjustment* - /// after instruction selection by calling a target hook. For example, this - /// can be used to fill in ARM 's' optional operand depending on whether - /// the conditional flag register is used. - bool hasPostISelHook() const { - return Flags & (1 << MCID::HasPostISelHook); - } + /// \brief Return true if this instruction requires *adjustment* after + /// instruction selection by calling a target hook. For example, this can be + /// used to fill in ARM 's' optional operand depending on whether the + /// conditional flag register is used. + bool hasPostISelHook() const { return Flags & (1 << MCID::HasPostISelHook); } - /// isRematerializable - Returns true if this instruction is a candidate for - /// remat. This flag is only used in TargetInstrInfo method - /// isTriviallyRematerializable. + /// \brief Returns true if this instruction is a candidate for remat. This + /// flag is only used in TargetInstrInfo method isTriviallyRematerializable. /// /// If this flag is set, the isReallyTriviallyReMaterializable() /// or isReallyTriviallyReMaterializableGeneric methods are called to verify @@ -506,80 +424,76 @@ public: return Flags & (1 << MCID::Rematerializable); } - /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or - /// less) than a move instruction. This is useful during certain types of - /// optimizations (e.g., remat during two-address conversion or machine licm) - /// where we would like to remat or hoist the instruction, but not if it costs - /// more than moving the instruction into the appropriate register. Note, we - /// are not marking copies from and to the same register class with this flag. + /// \brief Returns true if this instruction has the same cost (or less) than a + /// move instruction. This is useful during certain types of optimizations + /// (e.g., remat during two-address conversion or machine licm) where we would + /// like to remat or hoist the instruction, but not if it costs more than + /// moving the instruction into the appropriate register. Note, we are not + /// marking copies from and to the same register class with this flag. /// /// This method could be called by interface TargetInstrInfo::isAsCheapAsAMove /// for different subtargets. - bool isAsCheapAsAMove() const { - return Flags & (1 << MCID::CheapAsAMove); - } - - /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands - /// have special register allocation requirements that are not captured by the - /// operand register classes. e.g. ARM::STRD's two source registers must be an - /// even / odd pair, ARM::STM registers have to be in ascending order. - /// Post-register allocation passes should not attempt to change allocations - /// for sources of instructions with this flag. + bool isAsCheapAsAMove() const { return Flags & (1 << MCID::CheapAsAMove); } + + /// \brief Returns true if this instruction source operands have special + /// register allocation requirements that are not captured by the operand + /// register classes. e.g. ARM::STRD's two source registers must be an even / + /// odd pair, ARM::STM registers have to be in ascending order. Post-register + /// allocation passes should not attempt to change allocations for sources of + /// instructions with this flag. bool hasExtraSrcRegAllocReq() const { return Flags & (1 << MCID::ExtraSrcRegAllocReq); } - /// hasExtraDefRegAllocReq - Returns true if this instruction def operands - /// have special register allocation requirements that are not captured by the - /// operand register classes. e.g. ARM::LDRD's two def registers must be an - /// even / odd pair, ARM::LDM registers have to be in ascending order. - /// Post-register allocation passes should not attempt to change allocations - /// for definitions of instructions with this flag. + /// \brief Returns true if this instruction def operands have special register + /// allocation requirements that are not captured by the operand register + /// classes. e.g. ARM::LDRD's two def registers must be an even / odd pair, + /// ARM::LDM registers have to be in ascending order. Post-register + /// allocation passes should not attempt to change allocations for definitions + /// of instructions with this flag. bool hasExtraDefRegAllocReq() const { return Flags & (1 << MCID::ExtraDefRegAllocReq); } - - /// getImplicitUses - Return a list of registers that are potentially - /// read by any instance of this machine instruction. For example, on X86, - /// the "adc" instruction adds two register operands and adds the carry bit in - /// from the flags register. In this case, the instruction is marked as - /// implicitly reading the flags. Likewise, the variable shift instruction on - /// X86 is marked as implicitly reading the 'CL' register, which it always - /// does. + /// \brief Return a list of registers that are potentially read by any + /// instance of this machine instruction. For example, on X86, the "adc" + /// instruction adds two register operands and adds the carry bit in from the + /// flags register. In this case, the instruction is marked as implicitly + /// reading the flags. Likewise, the variable shift instruction on X86 is + /// marked as implicitly reading the 'CL' register, which it always does. /// /// This method returns null if the instruction has no implicit uses. - const uint16_t *getImplicitUses() const { - return ImplicitUses; - } + const uint16_t *getImplicitUses() const { return ImplicitUses; } /// \brief Return the number of implicit uses this instruction has. unsigned getNumImplicitUses() const { - if (!ImplicitUses) return 0; + if (!ImplicitUses) + return 0; unsigned i = 0; - for (; ImplicitUses[i]; ++i) /*empty*/; + for (; ImplicitUses[i]; ++i) /*empty*/ + ; return i; } - /// getImplicitDefs - Return a list of registers that are potentially - /// written by any instance of this machine instruction. For example, on X86, - /// many instructions implicitly set the flags register. In this case, they - /// are marked as setting the FLAGS. Likewise, many instructions always - /// deposit their result in a physical register. For example, the X86 divide + /// \brief Return a list of registers that are potentially written by any + /// instance of this machine instruction. For example, on X86, many + /// instructions implicitly set the flags register. In this case, they are + /// marked as setting the FLAGS. Likewise, many instructions always deposit + /// their result in a physical register. For example, the X86 divide /// instruction always deposits the quotient and remainder in the EAX/EDX /// registers. For that instruction, this will return a list containing the /// EAX/EDX/EFLAGS registers. /// /// This method returns null if the instruction has no implicit defs. - const uint16_t *getImplicitDefs() const { - return ImplicitDefs; - } + const uint16_t *getImplicitDefs() const { return ImplicitDefs; } /// \brief Return the number of implicit defs this instruct has. unsigned getNumImplicitDefs() const { - if (!ImplicitDefs) return 0; + if (!ImplicitDefs) + return 0; unsigned i = 0; - for (; ImplicitDefs[i]; ++i) /*empty*/; + for (; ImplicitDefs[i]; ++i) /*empty*/ + ; return i; } @@ -588,45 +502,25 @@ public: bool hasImplicitUseOfPhysReg(unsigned Reg) const { if (const uint16_t *ImpUses = ImplicitUses) for (; *ImpUses; ++ImpUses) - if (*ImpUses == Reg) return true; + if (*ImpUses == Reg) + return true; return false; } /// \brief Return true if this instruction implicitly /// defines the specified physical register. bool hasImplicitDefOfPhysReg(unsigned Reg, - const MCRegisterInfo *MRI = nullptr) const { - if (const uint16_t *ImpDefs = ImplicitDefs) - for (; *ImpDefs; ++ImpDefs) - if (*ImpDefs == Reg || (MRI && MRI->isSubRegister(Reg, *ImpDefs))) - return true; - return false; - } - - /// \brief Return true if this instruction defines the specified physical - /// register, either explicitly or implicitly. - bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, - const MCRegisterInfo &RI) const { - for (int i = 0, e = NumDefs; i != e; ++i) - if (MI.getOperand(i).isReg() && - RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg())) - return true; - return hasImplicitDefOfPhysReg(Reg, &RI); - } + const MCRegisterInfo *MRI = nullptr) const; /// \brief Return the scheduling class for this instruction. The /// scheduling class is an index into the InstrItineraryData table. This /// returns zero if there is no known scheduling information for the /// instruction. - unsigned getSchedClass() const { - return SchedClass; - } + unsigned getSchedClass() const { return SchedClass; } /// \brief Return the number of bytes in the encoding of this instruction, /// or zero if the encoding size cannot be known from the opcode. - unsigned getSize() const { - return Size; - } + unsigned getSize() const { return Size; } /// \brief Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if @@ -639,6 +533,13 @@ public: } return -1; } + +private: + + /// \brief Return true if this instruction defines the specified physical + /// register, either explicitly or implicitly. + bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, + const MCRegisterInfo &RI) const; }; } // end namespace llvm diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h index 1d3a36ca7c73a..70c86587b08c5 100644 --- a/include/llvm/MC/MCInstrInfo.h +++ b/include/llvm/MC/MCInstrInfo.h @@ -20,9 +20,7 @@ namespace llvm { //--------------------------------------------------------------------------- -/// -/// MCInstrInfo - Interface to description of machine instruction set -/// +/// \brief Interface to description of machine instruction set. class MCInstrInfo { const MCInstrDesc *Desc; // Raw array to allow static init'n const unsigned *InstrNameIndices; // Array for name indices in InstrNameData @@ -30,8 +28,8 @@ class MCInstrInfo { unsigned NumOpcodes; // Number of entries in the desc array public: - /// InitMCInstrInfo - Initialize MCInstrInfo, called by TableGen - /// auto-generated routines. *DO NOT USE*. + /// \brief Initialize MCInstrInfo, called by TableGen auto-generated routines. + /// *DO NOT USE*. void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND, unsigned NO) { Desc = D; @@ -42,15 +40,14 @@ public: unsigned getNumOpcodes() const { return NumOpcodes; } - /// get - Return the machine instruction descriptor that corresponds to the + /// \brief Return the machine instruction descriptor that corresponds to the /// specified instruction opcode. - /// const MCInstrDesc &get(unsigned Opcode) const { assert(Opcode < NumOpcodes && "Invalid opcode!"); return Desc[Opcode]; } - /// getName - Returns the name for the instructions with the given opcode. + /// \brief Returns the name for the instructions with the given opcode. const char *getName(unsigned Opcode) const { assert(Opcode < NumOpcodes && "Invalid opcode!"); return &InstrNameData[InstrNameIndices[Opcode]]; diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 94d599f672af5..161705de7c4e1 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -67,12 +67,12 @@ struct InstrStage { int NextCycles_; ///< Number of machine cycles to next stage ReservationKinds Kind_; ///< Kind of the FU reservation - /// Returns the number of cycles the stage is occupied. + /// \brief Returns the number of cycles the stage is occupied. unsigned getCycles() const { return Cycles_; } - /// Returns the choice of FUs. + /// \brief Returns the choice of FUs. unsigned getUnits() const { return Units_; } @@ -81,8 +81,8 @@ struct InstrStage { return Kind_; } - /// Returns the number of cycles from the start of - /// this stage to the start of the next stage in the itinerary + /// \brief Returns the number of cycles from the start of this stage to the + /// start of the next stage in the itinerary unsigned getNextCycles() const { return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; } @@ -115,7 +115,6 @@ public: const InstrItinerary *Itineraries; ///< Array of itineraries selected /// Ctors. - /// InstrItineraryData() : SchedModel(MCSchedModel::GetDefaultSchedModel()), Stages(nullptr), OperandCycles(nullptr), Forwardings(nullptr), Itineraries(nullptr) {} @@ -125,30 +124,30 @@ public: : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(SchedModel.InstrItineraries) {} - /// Returns true if there are no itineraries. + /// \brief Returns true if there are no itineraries. bool isEmpty() const { return Itineraries == nullptr; } - /// Returns true if the index is for the end marker itinerary. + /// \brief Returns true if the index is for the end marker itinerary. bool isEndMarker(unsigned ItinClassIndx) const { return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && (Itineraries[ItinClassIndx].LastStage == ~0U)); } - /// Return the first stage of the itinerary. + /// \brief Return the first stage of the itinerary. const InstrStage *beginStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; return Stages + StageIdx; } - /// Return the last+1 stage of the itinerary. + /// \brief Return the last+1 stage of the itinerary. const InstrStage *endStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; return Stages + StageIdx; } - /// Return the total stage latency of the given class. - /// The latency is the maximum completion time for any stage in the itinerary. - /// If no stages exist, it defaults to one cycle. + /// \brief Return the total stage latency of the given class. The latency is + /// the maximum completion time for any stage in the itinerary. If no stages + /// exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple // non-zero default value for all instructions. @@ -165,8 +164,8 @@ public: return Latency; } - /// Return the cycle for the given class and operand. - /// Return -1 if no cycle is specified for the operand. + /// \brief Return the cycle for the given class and operand. Return -1 if no + /// cycle is specified for the operand. int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { if (isEmpty()) return -1; @@ -179,11 +178,11 @@ public: return (int)OperandCycles[FirstIdx + OperandIdx]; } - /// Return true if there is a pipeline forwarding - /// between instructions of itinerary classes DefClass and UseClasses so that - /// value produced by an instruction of itinerary class DefClass, operand - /// index DefIdx can be bypassed when it's read by an instruction of - /// itinerary class UseClass, operand index UseIdx. + /// \brief Return true if there is a pipeline forwarding between instructions + /// of itinerary classes DefClass and UseClasses so that value produced by an + /// instruction of itinerary class DefClass, operand index DefIdx can be + /// bypassed when it's read by an instruction of itinerary class UseClass, + /// operand index UseIdx. bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const { unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; @@ -202,9 +201,9 @@ public: Forwardings[FirstUseIdx + UseIdx]; } - /// Compute and return the use operand latency of a given - /// itinerary class and operand index if the value is produced by an - /// instruction of the specified itinerary class and def operand index. + /// \brief Compute and return the use operand latency of a given itinerary + /// class and operand index if the value is produced by an instruction of the + /// specified itinerary class and def operand index. int getOperandLatency(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const { if (isEmpty()) @@ -226,7 +225,7 @@ public: return UseCycle; } - /// Return the number of micro-ops that the given class decodes to. + /// \brief Return the number of micro-ops that the given class decodes to. /// Return -1 for classes that require dynamic lookup via TargetInstrInfo. int getNumMicroOps(unsigned ItinClassIndx) const { if (isEmpty()) diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h index f531de8b40d99..de2d0af1423a4 100644 --- a/include/llvm/MC/MCLabel.h +++ b/include/llvm/MC/MCLabel.h @@ -20,11 +20,11 @@ namespace llvm { class MCContext; class raw_ostream; - /// MCLabel - Instances of this class represent a label name in the MC file, - /// and MCLabel are created and unique'd by the MCContext class. MCLabel + /// \brief Instances of this class represent a label name in the MC file, + /// and MCLabel are created and uniqued by the MCContext class. MCLabel /// should only be constructed for valid instances in the object file. class MCLabel { - // Instance - the instance number of this Directional Local Label + // \brief The instance number of this Directional Local Label. unsigned Instance; private: // MCContext creates and uniques these. @@ -32,20 +32,19 @@ namespace llvm { MCLabel(unsigned instance) : Instance(instance) {} - MCLabel(const MCLabel&) LLVM_DELETED_FUNCTION; - void operator=(const MCLabel&) LLVM_DELETED_FUNCTION; + MCLabel(const MCLabel&) = delete; + void operator=(const MCLabel&) = delete; public: - /// getInstance - Get the current instance of this Directional Local Label. + /// \brief Get the current instance of this Directional Local Label. unsigned getInstance() const { return Instance; } - /// incInstance - Increment the current instance of this Directional Local - /// Label. + /// \brief Increment the current instance of this Directional Local Label. unsigned incInstance() { return ++Instance; } - /// print - Print the value to the stream \p OS. + /// \brief Print the value to the stream \p OS. void print(raw_ostream &OS) const; - /// dump - Print the value to stderr. + /// \brief Print the value to stderr. void dump() const; }; diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index 890d6385aacde..a186a14b8001f 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -103,8 +103,8 @@ class MCLOHDirective { /// Arguments of this directive. Order matters. SmallVector<MCSymbol *, 3> Args; - /// Emit this directive in @p OutStream using the information available - /// in the given @p ObjWriter and @p Layout to get the address of the + /// Emit this directive in \p OutStream using the information available + /// in the given \p ObjWriter and \p Layout to get the address of the /// arguments within the object file. void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const; @@ -128,8 +128,8 @@ public: Emit_impl(OutStream, ObjWriter, Layout); } - /// Get the size in bytes of this directive if emitted in @p ObjWriter with - /// the given @p Layout. + /// Get the size in bytes of this directive if emitted in \p ObjWriter with + /// the given \p Layout. uint64_t getEmitSize(const MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { class raw_counting_ostream : public raw_ostream { @@ -141,7 +141,7 @@ public: public: raw_counting_ostream() : Count(0) {} - ~raw_counting_ostream() { flush(); } + ~raw_counting_ostream() override { flush(); } }; raw_counting_ostream OutStream; @@ -167,8 +167,8 @@ public: return Directives; } - /// Add the directive of the given kind @p Kind with the given arguments - /// @p Args to the container. + /// Add the directive of the given kind \p Kind with the given arguments + /// \p Args to the container. void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) { Directives.push_back(MCLOHDirective(Kind, Args)); } diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 0c5aa8a180638..63c2a28a7c9c8 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -21,7 +21,6 @@ namespace llvm { -class MCSectionData; class MachObjectWriter; class MCMachObjectTargetWriter { @@ -45,14 +44,14 @@ protected: public: virtual ~MCMachObjectTargetWriter(); - /// @name Lifetime Management + /// \name Lifetime Management /// @{ virtual void reset() {}; /// @} - /// @name Accessors + /// \name Accessors /// @{ bool is64Bit() const { return Is64Bit; } @@ -65,15 +64,13 @@ public: /// @} - /// @name API + /// \name API /// @{ - virtual void RecordRelocation(MachObjectWriter *Writer, - const MCAssembler &Asm, + virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; /// @} @@ -83,7 +80,7 @@ class MachObjectWriter : public MCObjectWriter { /// MachSymbolData - Helper struct for containing some precomputed information /// on symbols. struct MachSymbolData { - MCSymbolData *SymbolData; + const MCSymbol *Symbol; uint64_t StringIndex; uint8_t SectionIndex; @@ -94,15 +91,21 @@ class MachObjectWriter : public MCObjectWriter { /// The target specific Mach-O writer instance. std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter; - /// @name Relocation Data + /// \name Relocation Data /// @{ - llvm::DenseMap<const MCSectionData*, - std::vector<MachO::any_relocation_info> > Relocations; - llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase; + struct RelAndSymbol { + const MCSymbol *Sym; + MachO::any_relocation_info MRE; + RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE) + : Sym(Sym), MRE(MRE) {} + }; + + llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations; + llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase; /// @} - /// @name Symbol Table Data + /// \name Symbol Table Data /// @{ StringTableBuilder StringTable; @@ -115,19 +118,20 @@ class MachObjectWriter : public MCObjectWriter { MachSymbolData *findSymbolData(const MCSymbol &Sym); public: - MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, - bool _IsLittleEndian) - : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { - } + MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_pwrite_stream &OS, + bool IsLittleEndian) + : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} + + const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const; - /// @name Lifetime management Methods + /// \name Lifetime management Methods /// @{ void reset() override; /// @} - /// @name Utility Methods + /// \name Utility Methods /// @{ bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); @@ -136,23 +140,21 @@ public: SectionAddrMap &getSectionAddressMap() { return SectionAddress; } - uint64_t getSectionAddress(const MCSectionData* SD) const { - return SectionAddress.lookup(SD); + uint64_t getSectionAddress(const MCSection *Sec) const { + return SectionAddress.lookup(Sec); } - uint64_t getSymbolAddress(const MCSymbolData* SD, - const MCAsmLayout &Layout) const; + uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const; uint64_t getFragmentAddress(const MCFragment *Fragment, const MCAsmLayout &Layout) const; - uint64_t getPaddingSize(const MCSectionData *SD, - const MCAsmLayout &Layout) const; + uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const; - bool doesSymbolRequireExternRelocation(const MCSymbolData *SD); + bool doesSymbolRequireExternRelocation(const MCSymbol &S); /// @} - /// @name Target Writer Proxy Accessors + /// \name Target Writer Proxy Accessors /// @{ bool is64Bit() const { return TargetObjectWriter->is64Bit(); } @@ -176,7 +178,7 @@ public: uint64_t SectionDataSize); void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCSectionData &SD, uint64_t FileOffset, + const MCSection &Sec, uint64_t FileOffset, uint64_t RelocationsStart, unsigned NumRelocations); void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, @@ -213,9 +215,15 @@ public: // - Input errors, where something cannot be correctly encoded. 'as' allows // these through in many cases. - void addRelocation(const MCSectionData *SD, + // Add a relocation to be output in the object file. At the time this is + // called, the symbol indexes are not know, so if the relocation refers + // to a symbol it should be passed as \p RelSymbol so that it can be updated + // afterwards. If the relocation doesn't refer to a symbol, nullptr should be + // used. + void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec, MachO::any_relocation_info &MRE) { - Relocations[SD].push_back(MRE); + RelAndSymbol P(RelSymbol, MRE); + Relocations[Sec].push_back(P); } void RecordScatteredRelocation(const MCAssembler &Asm, @@ -231,7 +239,7 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; @@ -248,15 +256,12 @@ public: void computeSectionAddresses(const MCAssembler &Asm, const MCAsmLayout &Layout); - void markAbsoluteVariableSymbols(MCAssembler &Asm, - const MCAsmLayout &Layout); void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, + const MCSymbol &SymA, + const MCFragment &FB, bool InSet, bool IsPCRel) const override; void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; @@ -271,7 +276,8 @@ public: /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW, - raw_ostream &OS, bool IsLittleEndian); + raw_pwrite_stream &OS, + bool IsLittleEndian); } // End llvm namespace diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 321043c522ee4..f28b9c668cdc8 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -53,144 +53,139 @@ protected: /// should emit only an EH frame. unsigned CompactUnwindDwarfEHFrameOnly; - /// TextSection - Section directive for standard text. + /// Section directive for standard text. /// - const MCSection *TextSection; + MCSection *TextSection; - /// DataSection - Section directive for standard data. + /// Section directive for standard data. /// - const MCSection *DataSection; + MCSection *DataSection; - /// BSSSection - Section that is default initialized to zero. - const MCSection *BSSSection; + /// Section that is default initialized to zero. + MCSection *BSSSection; - /// ReadOnlySection - Section that is readonly and can contain arbitrary - /// initialized data. Targets are not required to have a readonly section. - /// If they don't, various bits of code will fall back to using the data - /// section for constants. - const MCSection *ReadOnlySection; + /// Section that is readonly and can contain arbitrary initialized data. + /// Targets are not required to have a readonly section. If they don't, + /// various bits of code will fall back to using the data section for + /// constants. + MCSection *ReadOnlySection; - /// StaticCtorSection - This section contains the static constructor pointer - /// list. - const MCSection *StaticCtorSection; + /// This section contains the static constructor pointer list. + MCSection *StaticCtorSection; - /// StaticDtorSection - This section contains the static destructor pointer - /// list. - const MCSection *StaticDtorSection; + /// This section contains the static destructor pointer list. + MCSection *StaticDtorSection; - /// LSDASection - If exception handling is supported by the target, this is - /// the section the Language Specific Data Area information is emitted to. - const MCSection *LSDASection; + /// If exception handling is supported by the target, this is the section the + /// Language Specific Data Area information is emitted to. + MCSection *LSDASection; - /// CompactUnwindSection - If exception handling is supported by the target - /// and the target can support a compact representation of the CIE and FDE, - /// this is the section to emit them into. - const MCSection *CompactUnwindSection; + /// If exception handling is supported by the target and the target can + /// support a compact representation of the CIE and FDE, this is the section + /// to emit them into. + MCSection *CompactUnwindSection; // Dwarf sections for debug info. If a target supports debug info, these must // be set. - const MCSection *DwarfAbbrevSection; - const MCSection *DwarfInfoSection; - const MCSection *DwarfLineSection; - const MCSection *DwarfFrameSection; - const MCSection *DwarfPubTypesSection; + MCSection *DwarfAbbrevSection; + MCSection *DwarfInfoSection; + MCSection *DwarfLineSection; + MCSection *DwarfFrameSection; + MCSection *DwarfPubTypesSection; const MCSection *DwarfDebugInlineSection; - const MCSection *DwarfStrSection; - const MCSection *DwarfLocSection; - const MCSection *DwarfARangesSection; - const MCSection *DwarfRangesSection; - const MCSection *DwarfMacroInfoSection; + MCSection *DwarfStrSection; + MCSection *DwarfLocSection; + MCSection *DwarfARangesSection; + MCSection *DwarfRangesSection; // The pubnames section is no longer generated by default. The generation // can be enabled by a compiler flag. - const MCSection *DwarfPubNamesSection; + MCSection *DwarfPubNamesSection; // DWARF5 Experimental Debug Info Sections /// DwarfAccelNamesSection, DwarfAccelObjCSection, /// DwarfAccelNamespaceSection, DwarfAccelTypesSection - /// If we use the DWARF accelerated hash tables then we want to emit these /// sections. - const MCSection *DwarfAccelNamesSection; - const MCSection *DwarfAccelObjCSection; - const MCSection *DwarfAccelNamespaceSection; - const MCSection *DwarfAccelTypesSection; + MCSection *DwarfAccelNamesSection; + MCSection *DwarfAccelObjCSection; + MCSection *DwarfAccelNamespaceSection; + MCSection *DwarfAccelTypesSection; /// These are used for the Fission separate debug information files. - const MCSection *DwarfInfoDWOSection; - const MCSection *DwarfTypesDWOSection; - const MCSection *DwarfAbbrevDWOSection; - const MCSection *DwarfStrDWOSection; - const MCSection *DwarfLineDWOSection; - const MCSection *DwarfLocDWOSection; - const MCSection *DwarfStrOffDWOSection; - const MCSection *DwarfAddrSection; + MCSection *DwarfInfoDWOSection; + MCSection *DwarfTypesDWOSection; + MCSection *DwarfAbbrevDWOSection; + MCSection *DwarfStrDWOSection; + MCSection *DwarfLineDWOSection; + MCSection *DwarfLocDWOSection; + MCSection *DwarfStrOffDWOSection; + MCSection *DwarfAddrSection; /// Sections for newer gnu pubnames and pubtypes. - const MCSection *DwarfGnuPubNamesSection; - const MCSection *DwarfGnuPubTypesSection; + MCSection *DwarfGnuPubNamesSection; + MCSection *DwarfGnuPubTypesSection; - const MCSection *COFFDebugSymbolsSection; + MCSection *COFFDebugSymbolsSection; // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. - const MCSection *TLSExtraDataSection; + MCSection *TLSExtraDataSection; - /// TLSDataSection - Section directive for Thread Local data. - /// ELF, MachO and COFF. - const MCSection *TLSDataSection; // Defaults to ".tdata". + /// Section directive for Thread Local data. ELF, MachO and COFF. + MCSection *TLSDataSection; // Defaults to ".tdata". - /// TLSBSSSection - Section directive for Thread Local uninitialized data. - /// Null if this target doesn't support a BSS section. - /// ELF and MachO only. - const MCSection *TLSBSSSection; // Defaults to ".tbss". + /// Section directive for Thread Local uninitialized data. Null if this target + /// doesn't support a BSS section. ELF and MachO only. + MCSection *TLSBSSSection; // Defaults to ".tbss". /// StackMap section. - const MCSection *StackMapSection; + MCSection *StackMapSection; - /// EHFrameSection - EH frame section. It is initialized on demand so it - /// can be overwritten (with uniquing). - const MCSection *EHFrameSection; + /// EH frame section. It is initialized on demand so it can be overwritten + /// (with uniquing). + MCSection *EHFrameSection; /// ELF specific sections. /// - const MCSection *DataRelSection; + MCSection *DataRelSection; const MCSection *DataRelLocalSection; - const MCSection *DataRelROSection; - const MCSection *DataRelROLocalSection; - const MCSection *MergeableConst4Section; - const MCSection *MergeableConst8Section; - const MCSection *MergeableConst16Section; + MCSection *DataRelROSection; + MCSection *DataRelROLocalSection; + MCSection *MergeableConst4Section; + MCSection *MergeableConst8Section; + MCSection *MergeableConst16Section; /// MachO specific sections. /// - /// TLSTLVSection - Section for thread local structure information. - /// Contains the source code name of the variable, visibility and a pointer - /// to the initial value (.tdata or .tbss). - const MCSection *TLSTLVSection; // Defaults to ".tlv". + /// Section for thread local structure information. Contains the source code + /// name of the variable, visibility and a pointer to the initial value + /// (.tdata or .tbss). + MCSection *TLSTLVSection; // Defaults to ".tlv". /// TLSThreadInitSection - Section for thread local data initialization /// functions. const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". - const MCSection *CStringSection; - const MCSection *UStringSection; - const MCSection *TextCoalSection; - const MCSection *ConstTextCoalSection; - const MCSection *ConstDataSection; - const MCSection *DataCoalSection; - const MCSection *DataCommonSection; - const MCSection *DataBSSSection; - const MCSection *FourByteConstantSection; - const MCSection *EightByteConstantSection; - const MCSection *SixteenByteConstantSection; - const MCSection *LazySymbolPointerSection; - const MCSection *NonLazySymbolPointerSection; + MCSection *CStringSection; + MCSection *UStringSection; + MCSection *TextCoalSection; + MCSection *ConstTextCoalSection; + MCSection *ConstDataSection; + MCSection *DataCoalSection; + MCSection *DataCommonSection; + MCSection *DataBSSSection; + MCSection *FourByteConstantSection; + MCSection *EightByteConstantSection; + MCSection *SixteenByteConstantSection; + MCSection *LazySymbolPointerSection; + MCSection *NonLazySymbolPointerSection; /// COFF specific sections. /// - const MCSection *DrectveSection; - const MCSection *PDataSection; - const MCSection *XDataSection; + MCSection *DrectveSection; + MCSection *PDataSection; + MCSection *XDataSection; public: void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, @@ -215,97 +210,70 @@ public: return CompactUnwindDwarfEHFrameOnly; } - const MCSection *getTextSection() const { return TextSection; } - const MCSection *getDataSection() const { return DataSection; } - const MCSection *getBSSSection() const { return BSSSection; } - const MCSection *getLSDASection() const { return LSDASection; } - const MCSection *getCompactUnwindSection() const{ - return CompactUnwindSection; - } - const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } - const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } - const MCSection *getDwarfLineSection() const { return DwarfLineSection; } - const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } - const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} - const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} - const MCSection *getDwarfGnuPubNamesSection() const { + MCSection *getTextSection() const { return TextSection; } + MCSection *getDataSection() const { return DataSection; } + MCSection *getBSSSection() const { return BSSSection; } + MCSection *getLSDASection() const { return LSDASection; } + MCSection *getCompactUnwindSection() const { return CompactUnwindSection; } + MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } + MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } + MCSection *getDwarfLineSection() const { return DwarfLineSection; } + MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } + MCSection *getDwarfPubNamesSection() const { return DwarfPubNamesSection; } + MCSection *getDwarfPubTypesSection() const { return DwarfPubTypesSection; } + MCSection *getDwarfGnuPubNamesSection() const { return DwarfGnuPubNamesSection; } - const MCSection *getDwarfGnuPubTypesSection() const { + MCSection *getDwarfGnuPubTypesSection() const { return DwarfGnuPubTypesSection; } const MCSection *getDwarfDebugInlineSection() const { return DwarfDebugInlineSection; } - const MCSection *getDwarfStrSection() const { return DwarfStrSection; } - const MCSection *getDwarfLocSection() const { return DwarfLocSection; } - const MCSection *getDwarfARangesSection() const { return DwarfARangesSection;} - const MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } - const MCSection *getDwarfMacroInfoSection() const { - return DwarfMacroInfoSection; - } + MCSection *getDwarfStrSection() const { return DwarfStrSection; } + MCSection *getDwarfLocSection() const { return DwarfLocSection; } + MCSection *getDwarfARangesSection() const { return DwarfARangesSection; } + MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } // DWARF5 Experimental Debug Info Sections - const MCSection *getDwarfAccelNamesSection() const { + MCSection *getDwarfAccelNamesSection() const { return DwarfAccelNamesSection; } - const MCSection *getDwarfAccelObjCSection() const { - return DwarfAccelObjCSection; - } - const MCSection *getDwarfAccelNamespaceSection() const { + MCSection *getDwarfAccelObjCSection() const { return DwarfAccelObjCSection; } + MCSection *getDwarfAccelNamespaceSection() const { return DwarfAccelNamespaceSection; } - const MCSection *getDwarfAccelTypesSection() const { + MCSection *getDwarfAccelTypesSection() const { return DwarfAccelTypesSection; } - const MCSection *getDwarfInfoDWOSection() const { - return DwarfInfoDWOSection; - } - const MCSection *getDwarfTypesSection(uint64_t Hash) const; - const MCSection *getDwarfTypesDWOSection() const { - return DwarfTypesDWOSection; - } - const MCSection *getDwarfAbbrevDWOSection() const { - return DwarfAbbrevDWOSection; - } - const MCSection *getDwarfStrDWOSection() const { - return DwarfStrDWOSection; - } - const MCSection *getDwarfLineDWOSection() const { - return DwarfLineDWOSection; - } - const MCSection *getDwarfLocDWOSection() const { - return DwarfLocDWOSection; - } - const MCSection *getDwarfStrOffDWOSection() const { - return DwarfStrOffDWOSection; - } - const MCSection *getDwarfAddrSection() const { - return DwarfAddrSection; - } - - const MCSection *getCOFFDebugSymbolsSection() const { + MCSection *getDwarfInfoDWOSection() const { return DwarfInfoDWOSection; } + MCSection *getDwarfTypesSection(uint64_t Hash) const; + MCSection *getDwarfTypesDWOSection() const { return DwarfTypesDWOSection; } + MCSection *getDwarfAbbrevDWOSection() const { return DwarfAbbrevDWOSection; } + MCSection *getDwarfStrDWOSection() const { return DwarfStrDWOSection; } + MCSection *getDwarfLineDWOSection() const { return DwarfLineDWOSection; } + MCSection *getDwarfLocDWOSection() const { return DwarfLocDWOSection; } + MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; } + MCSection *getDwarfAddrSection() const { return DwarfAddrSection; } + + MCSection *getCOFFDebugSymbolsSection() const { return COFFDebugSymbolsSection; } - const MCSection *getTLSExtraDataSection() const { - return TLSExtraDataSection; - } + MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; } const MCSection *getTLSDataSection() const { return TLSDataSection; } - const MCSection *getTLSBSSSection() const { return TLSBSSSection; } + MCSection *getTLSBSSSection() const { return TLSBSSSection; } - const MCSection *getStackMapSection() const { return StackMapSection; } + MCSection *getStackMapSection() const { return StackMapSection; } /// ELF specific sections. /// - const MCSection *getDataRelSection() const { return DataRelSection; } + MCSection *getDataRelSection() const { return DataRelSection; } const MCSection *getDataRelLocalSection() const { return DataRelLocalSection; } - const MCSection *getDataRelROSection() const { return DataRelROSection; } - const MCSection *getDataRelROLocalSection() const { - return DataRelROLocalSection; - } + MCSection *getDataRelROSection() const { return DataRelROSection; } + MCSection *getDataRelROLocalSection() const { return DataRelROLocalSection; } const MCSection *getMergeableConst4Section() const { return MergeableConst4Section; } @@ -324,14 +292,14 @@ public: } const MCSection *getCStringSection() const { return CStringSection; } const MCSection *getUStringSection() const { return UStringSection; } - const MCSection *getTextCoalSection() const { return TextCoalSection; } + MCSection *getTextCoalSection() const { return TextCoalSection; } const MCSection *getConstTextCoalSection() const { return ConstTextCoalSection; } const MCSection *getConstDataSection() const { return ConstDataSection; } const MCSection *getDataCoalSection() const { return DataCoalSection; } const MCSection *getDataCommonSection() const { return DataCommonSection; } - const MCSection *getDataBSSSection() const { return DataBSSSection; } + MCSection *getDataBSSSection() const { return DataBSSSection; } const MCSection *getFourByteConstantSection() const { return FourByteConstantSection; } @@ -341,20 +309,20 @@ public: const MCSection *getSixteenByteConstantSection() const { return SixteenByteConstantSection; } - const MCSection *getLazySymbolPointerSection() const { + MCSection *getLazySymbolPointerSection() const { return LazySymbolPointerSection; } - const MCSection *getNonLazySymbolPointerSection() const { + MCSection *getNonLazySymbolPointerSection() const { return NonLazySymbolPointerSection; } /// COFF specific sections. /// - const MCSection *getDrectveSection() const { return DrectveSection; } - const MCSection *getPDataSection() const { return PDataSection; } - const MCSection *getXDataSection() const { return XDataSection; } + MCSection *getDrectveSection() const { return DrectveSection; } + MCSection *getPDataSection() const { return PDataSection; } + MCSection *getXDataSection() const { return XDataSection; } - const MCSection *getEHFrameSection() { + MCSection *getEHFrameSection() { if (!EHFrameSection) InitEHFrameSection(); return EHFrameSection; diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 0866ff5a9fc08..e75bc86cc131b 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -12,18 +12,19 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" namespace llvm { class MCAssembler; class MCCodeEmitter; -class MCSectionData; class MCSubtargetInfo; class MCExpr; class MCFragment; class MCDataFragment; class MCAsmBackend; class raw_ostream; +class raw_pwrite_stream; /// \brief Streaming object file generation interface. /// @@ -34,8 +35,8 @@ class raw_ostream; /// implementation. class MCObjectStreamer : public MCStreamer { MCAssembler *Assembler; - MCSectionData *CurSectionData; - MCSectionData::iterator CurInsertionPoint; + MCSection *CurSectionData; + MCSection::iterator CurInsertionPoint; bool EmitEHFrame; bool EmitDebugFrame; SmallVector<MCSymbolData *, 2> PendingLabels; @@ -44,16 +45,10 @@ class MCObjectStreamer : public MCStreamer { void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; - // If any labels have been emitted but not assigned fragments, ensure that - // they get assigned, either to F if possible or to a new data fragment. - void flushPendingLabels(MCFragment *F); - protected: - MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, - MCCodeEmitter *_Emitter); - MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, - MCCodeEmitter *_Emitter, MCAssembler *_Assembler); - ~MCObjectStreamer(); + MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter); + ~MCObjectStreamer() override; public: /// state management @@ -69,9 +64,7 @@ public: void EmitCFISections(bool EH, bool Debug) override; protected: - MCSectionData *getCurrentSectionData() const { - return CurSectionData; - } + MCSection *getCurrentSectionData() const { return CurSectionData; } MCFragment *getCurrentFragment() const; @@ -85,12 +78,20 @@ protected: /// fragment is not a data fragment. MCDataFragment *getOrCreateDataFragment(); + bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection); + + /// If any labels have been emitted but not assigned fragments, ensure that + /// they get assigned, either to F if possible or to a new data fragment. + /// Optionally, it is also possible to provide an offset \p FOffset, which + /// will be used as a symbol offset within the fragment. + void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0); + public: void visitUsedSymbol(const MCSymbol &Sym) override; MCAssembler &getAssembler() { return *Assembler; } - /// @name MCStreamer Interface + /// \name MCStreamer Interface /// @{ void EmitLabel(MCSymbol *Symbol) override; @@ -100,8 +101,7 @@ public: void EmitULEB128Value(const MCExpr *Value) override; void EmitSLEB128Value(const MCExpr *Value) override; void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; - void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) override; + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo& STI) override; /// \brief Emit an instruction to a special fragment, because this instruction @@ -133,9 +133,18 @@ public: void EmitZeros(uint64_t NumBytes) override; void FinishImpl() override; - bool mayHaveInstructions() const override { - return getCurrentSectionData()->hasInstructions(); - } + /// Emit the absolute difference between two symbols if possible. + /// + /// Emit the absolute difference between \c Hi and \c Lo, as long as we can + /// compute it. Currently, that requires that both symbols are in the same + /// data fragment. Otherwise, do nothing and return \c false. + /// + /// \pre Offset of \c Hi is greater than the offset \c Lo. + /// \return true on success. + bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) override; + + bool mayHaveInstructions(MCSection &Sec) const override; }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 55c828c6c179e..999d294712709 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" #include <cassert> @@ -37,17 +38,17 @@ class MCValue; /// The object writer also contains a number of helper methods for writing /// binary data to the output stream. class MCObjectWriter { - MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION; - void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION; + MCObjectWriter(const MCObjectWriter &) = delete; + void operator=(const MCObjectWriter &) = delete; protected: - raw_ostream &OS; + raw_pwrite_stream &OS; unsigned IsLittleEndian : 1; protected: // Can only create subclasses. - MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian) - : OS(_OS), IsLittleEndian(_IsLittleEndian) {} + MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian) + : OS(OS), IsLittleEndian(IsLittleEndian) {} public: virtual ~MCObjectWriter(); @@ -59,7 +60,7 @@ public: raw_ostream &getStream() { return OS; } - /// @name High-Level API + /// \name High-Level API /// @{ /// \brief Perform any late binding of symbols (for example, to assign symbol @@ -76,30 +77,31 @@ public: /// post layout binding. The implementation is responsible for storing /// information about the relocation so that it can be emitted during /// WriteObject(). - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, + virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) = 0; + bool &IsPCRel, uint64_t &FixedValue) = 0; /// \brief Check whether the difference (A - B) between two symbol /// references is fully resolved. /// /// Clients are not required to answer precisely and may conservatively return /// false, even when a difference is fully resolved. - bool - IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, - const MCSymbolRefExpr *A, - const MCSymbolRefExpr *B, - bool InSet) const; - - virtual bool - IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const; + bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, + const MCSymbolRefExpr *A, + const MCSymbolRefExpr *B, + bool InSet) const; + + virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbol &SymA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + /// \brief True if this symbol (which is a variable) is weak. This is not + /// just STB_WEAK, but more generally whether or not we can evaluate + /// past it. + virtual bool isWeak(const MCSymbol &Sym) const; /// \brief Write the object file. /// @@ -110,7 +112,7 @@ public: const MCAsmLayout &Layout) = 0; /// @} - /// @name Binary Output + /// \name Binary Output /// @{ void Write8(uint8_t Value) { @@ -118,33 +120,27 @@ public: } void WriteLE16(uint16_t Value) { - Write8(uint8_t(Value >> 0)); - Write8(uint8_t(Value >> 8)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteLE32(uint32_t Value) { - WriteLE16(uint16_t(Value >> 0)); - WriteLE16(uint16_t(Value >> 16)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteLE64(uint64_t Value) { - WriteLE32(uint32_t(Value >> 0)); - WriteLE32(uint32_t(Value >> 32)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteBE16(uint16_t Value) { - Write8(uint8_t(Value >> 8)); - Write8(uint8_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void WriteBE32(uint32_t Value) { - WriteBE16(uint16_t(Value >> 16)); - WriteBE16(uint16_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void WriteBE64(uint64_t Value) { - WriteBE32(uint32_t(Value >> 32)); - WriteBE32(uint32_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void Write16(uint16_t Value) { diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index a9a30f1720712..62d39b26c8600 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -31,8 +31,8 @@ class AsmLexer : public MCAsmLexer { StringRef CurBuf; bool isAtStartOfLine; - void operator=(const AsmLexer&) LLVM_DELETED_FUNCTION; - AsmLexer(const AsmLexer&) LLVM_DELETED_FUNCTION; + void operator=(const AsmLexer&) = delete; + AsmLexer(const AsmLexer&) = delete; protected: /// LexToken - Read the next token and return its code. @@ -40,7 +40,7 @@ protected: public: AsmLexer(const MCAsmInfo &MAI); - ~AsmLexer(); + ~AsmLexer() override; void setBuffer(StringRef Buf, const char *ptr = nullptr); diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index b05891c13250b..71f15b37c331e 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -63,10 +63,10 @@ private: public: AsmToken() {} - AsmToken(TokenKind _Kind, StringRef _Str, APInt _IntVal) - : Kind(_Kind), Str(_Str), IntVal(_IntVal) {} - AsmToken(TokenKind _Kind, StringRef _Str, int64_t _IntVal = 0) - : Kind(_Kind), Str(_Str), IntVal(64, _IntVal, true) {} + AsmToken(TokenKind Kind, StringRef Str, APInt IntVal) + : Kind(Kind), Str(Str), IntVal(IntVal) {} + AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0) + : Kind(Kind), Str(Str), IntVal(64, IntVal, true) {} TokenKind getKind() const { return Kind; } bool is(TokenKind K) const { return Kind == K; } @@ -124,8 +124,8 @@ class MCAsmLexer { SMLoc ErrLoc; std::string Err; - MCAsmLexer(const MCAsmLexer &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmLexer &) LLVM_DELETED_FUNCTION; + MCAsmLexer(const MCAsmLexer &) = delete; + void operator=(const MCAsmLexer &) = delete; protected: // Can only create subclasses. const char *TokStart; bool SkipSpace; diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 34188e66e62da..0538b9457f9eb 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -45,7 +45,7 @@ public: } }; -/// Generic Sema callback for assembly parser. +/// \brief Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: virtual ~MCAsmParserSemaCallback(); @@ -59,8 +59,8 @@ public: unsigned &Offset) = 0; }; -/// Generic assembler parser interface, for use by target specific assembly -/// parsers. +/// \brief Generic assembler parser interface, for use by target specific +/// assembly parsers. class MCAsmParser { public: typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc); @@ -68,8 +68,8 @@ public: ExtensionDirectiveHandler; private: - MCAsmParser(const MCAsmParser &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmParser &) LLVM_DELETED_FUNCTION; + MCAsmParser(const MCAsmParser &) = delete; + void operator=(const MCAsmParser &) = delete; MCTargetAsmParser *TargetParser; @@ -84,6 +84,8 @@ public: virtual void addDirectiveHandler(StringRef Directive, ExtensionDirectiveHandler Handler) = 0; + virtual void addAliasForDirective(StringRef Directive, StringRef Alias) = 0; + virtual SourceMgr &getSourceManager() = 0; virtual MCAsmLexer &getLexer() = 0; @@ -93,7 +95,7 @@ public: virtual MCContext &getContext() = 0; - /// Return the output streamer for the assembler. + /// \brief Return the output streamer for the assembler. virtual MCStreamer &getStreamer() = 0; MCTargetAsmParser &getTargetParser() const { return *TargetParser; } @@ -105,13 +107,13 @@ public: bool getShowParsedOperands() const { return ShowParsedOperands; } void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } - /// Run the parser on the input source buffer. + /// \brief Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; virtual void setParsingInlineAsm(bool V) = 0; virtual bool isParsingInlineAsm() = 0; - /// Parse ms-style inline assembly. + /// \brief Parse MS-style inline assembly. virtual bool parseMSInlineAsm( void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, @@ -119,35 +121,35 @@ public: SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; - /// Emit a note at the location \p L, with the message \p Msg. + /// \brief Emit a note at the location \p L, with the message \p Msg. virtual void Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Emit a warning at the location \p L, with the message \p Msg. + /// \brief Emit a warning at the location \p L, with the message \p Msg. /// /// \return The return value is true, if warnings are fatal. virtual bool Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Emit an error at the location \p L, with the message \p Msg. + /// \brief Emit an error at the location \p L, with the message \p Msg. /// /// \return The return value is always true, as an idiomatic convenience to /// clients. virtual bool Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) = 0; - /// Get the next AsmToken in the stream, possibly handling file inclusion - /// first. + /// \brief Get the next AsmToken in the stream, possibly handling file + /// inclusion first. virtual const AsmToken &Lex() = 0; - /// Get the current AsmToken from the stream. + /// \brief Get the current AsmToken from the stream. const AsmToken &getTok() const; /// \brief Report an error at the current lexer location. bool TokError(const Twine &Msg, ArrayRef<SMRange> Ranges = None); - /// Parse an identifier or string (as a quoted identifier) and set \p Res to - /// the identifier contents. + /// \brief Parse an identifier or string (as a quoted identifier) and set \p + /// Res to the identifier contents. virtual bool parseIdentifier(StringRef &Res) = 0; /// \brief Parse up to the end of statement and return the contents from the @@ -155,51 +157,51 @@ public: /// will be either the EndOfStatement or EOF. virtual StringRef parseStringToEndOfStatement() = 0; - /// Parse the current token as a string which may include escaped characters - /// and return the string contents. + /// \brief Parse the current token as a string which may include escaped + /// characters and return the string contents. virtual bool parseEscapedString(std::string &Data) = 0; - /// Skip to the end of the current statement, for error recovery. + /// \brief Skip to the end of the current statement, for error recovery. virtual void eatToEndOfStatement() = 0; - /// Parse an arbitrary expression. + /// \brief Parse an arbitrary expression. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; bool parseExpression(const MCExpr *&Res); - /// Parse a primary expression. + /// \brief Parse a primary expression. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// Parse an arbitrary expression, assuming that an initial '(' has already - /// been consumed. + /// \brief Parse an arbitrary expression, assuming that an initial '(' has + /// already been consumed. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// Parse an expression which must evaluate to an absolute value. + /// \brief Parse an expression which must evaluate to an absolute value. /// - /// @param Res - The value of the absolute expression. The result is undefined + /// \param Res - The value of the absolute expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseAbsoluteExpression(int64_t &Res) = 0; - /// Ensure that we have a valid section set in the streamer. Otherwise, report - /// an error and switch to .text. + /// \brief Ensure that we have a valid section set in the streamer. Otherwise, + /// report an error and switch to .text. virtual void checkForValidSection() = 0; }; /// \brief Create an MCAsmParser instance. -MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, - MCStreamer &, const MCAsmInfo &); +MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, + const MCAsmInfo &); } // End llvm namespace diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index bfc0afa132b7f..077fd21e073ce 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -21,8 +21,8 @@ class Twine; /// which is implemented by target and object file assembly parser /// implementations. class MCAsmParserExtension { - MCAsmParserExtension(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION; + MCAsmParserExtension(const MCAsmParserExtension &) = delete; + void operator=(const MCAsmParserExtension &) = delete; MCAsmParser *Parser; @@ -48,7 +48,7 @@ public: /// parsing routines. virtual void Initialize(MCAsmParser &Parser); - /// @name MCAsmParser Proxy Interfaces + /// \name MCAsmParser Proxy Interfaces /// @{ MCContext &getContext() { return getParser().getContext(); } diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index e8740aa10aa2a..a25108a0effb0 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -10,8 +10,11 @@ #ifndef LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H #define LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H +#include <string> +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" + namespace llvm { -class SMLoc; class raw_ostream; /// MCParsedAsmOperand - This abstract class represents a source-level assembly diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCRelocationInfo.h index 9dab90099b7d1..40e0217b8d830 100644 --- a/include/llvm/MC/MCRelocationInfo.h +++ b/include/llvm/MC/MCRelocationInfo.h @@ -28,8 +28,8 @@ class MCContext; /// \brief Create MCExprs from relocations found in an object file. class MCRelocationInfo { - MCRelocationInfo(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; - void operator=(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; + MCRelocationInfo(const MCRelocationInfo &) = delete; + void operator=(const MCRelocationInfo &) = delete; protected: MCContext &Ctx; diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index de2678adad61c..96a4ef135f217 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -14,66 +14,163 @@ #ifndef LLVM_MC_MCSECTION_H #define LLVM_MC_MCSECTION_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Compiler.h" namespace llvm { - class MCAsmInfo; - class MCExpr; - class raw_ostream; - - /// MCSection - Instances of this class represent a uniqued identifier for a - /// section in the current translation unit. The MCContext class uniques and - /// creates these. - class MCSection { - public: - enum SectionVariant { - SV_COFF = 0, - SV_ELF, - SV_MachO - }; - - private: - MCSection(const MCSection&) LLVM_DELETED_FUNCTION; - void operator=(const MCSection&) LLVM_DELETED_FUNCTION; - protected: - MCSection(SectionVariant V, SectionKind K) : Variant(V), Kind(K) {} - SectionVariant Variant; - SectionKind Kind; - public: - virtual ~MCSection(); - - SectionKind getKind() const { return Kind; } - - SectionVariant getVariant() const { return Variant; } - - virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS, - const MCExpr *Subsection) const = 0; - - // Convenience routines to get label names for the beginning/end of a - // section. - virtual std::string getLabelBeginName() const = 0; - virtual std::string getLabelEndName() const = 0; - - /// isBaseAddressKnownZero - Return true if we know that this section will - /// get a base address of zero. In cases where we know that this is true we - /// can emit section offsets as direct references to avoid a subtraction - /// from the base of the section, saving a relocation. - virtual bool isBaseAddressKnownZero() const { - return false; - } - - // UseCodeAlign - Return true if a .align directive should use - // "optimized nops" to fill instead of 0s. - virtual bool UseCodeAlign() const = 0; - - /// isVirtualSection - Check whether this section is "virtual", that is - /// has no actual object file contents. - virtual bool isVirtualSection() const = 0; +class MCAssembler; +class MCAsmInfo; +class MCContext; +class MCExpr; +class MCFragment; +class MCSection; +class MCSymbol; +class raw_ostream; + +/// Instances of this class represent a uniqued identifier for a section in the +/// current translation unit. The MCContext class uniques and creates these. +class MCSection { +public: + enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO }; + + /// \brief Express the state of bundle locked groups while emitting code. + enum BundleLockStateType { + NotBundleLocked, + BundleLocked, + BundleLockedAlignToEnd }; + typedef iplist<MCFragment> FragmentListType; + + typedef FragmentListType::const_iterator const_iterator; + typedef FragmentListType::iterator iterator; + + typedef FragmentListType::const_reverse_iterator const_reverse_iterator; + typedef FragmentListType::reverse_iterator reverse_iterator; + +private: + MCSection(const MCSection &) = delete; + void operator=(const MCSection &) = delete; + + MCSymbol *Begin; + MCSymbol *End = nullptr; + /// The alignment requirement of this section. + unsigned Alignment = 1; + /// The section index in the assemblers section list. + unsigned Ordinal = 0; + /// The index of this section in the layout order. + unsigned LayoutOrder; + + /// \brief Keeping track of bundle-locked state. + BundleLockStateType BundleLockState = NotBundleLocked; + + /// \brief Current nesting depth of bundle_lock directives. + unsigned BundleLockNestingDepth = 0; + + /// \brief We've seen a bundle_lock directive but not its first instruction + /// yet. + bool BundleGroupBeforeFirstInst = false; + + /// Whether this section has had instructions emitted into it. + unsigned HasInstructions : 1; + + FragmentListType Fragments; + + /// Mapping from subsection number to insertion point for subsection numbers + /// below that number. + SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap; + +protected: + MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin); + SectionVariant Variant; + SectionKind Kind; + +public: + virtual ~MCSection(); + + SectionKind getKind() const { return Kind; } + + SectionVariant getVariant() const { return Variant; } + + MCSymbol *getBeginSymbol() { return Begin; } + const MCSymbol *getBeginSymbol() const { + return const_cast<MCSection *>(this)->getBeginSymbol(); + } + void setBeginSymbol(MCSymbol *Sym) { + assert(!Begin); + Begin = Sym; + } + MCSymbol *getEndSymbol(MCContext &Ctx); + bool hasEnded() const; + + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Value) { Alignment = Value; } + + unsigned getOrdinal() const { return Ordinal; } + void setOrdinal(unsigned Value) { Ordinal = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + BundleLockStateType getBundleLockState() const { return BundleLockState; } + void setBundleLockState(BundleLockStateType NewState); + bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } + + bool isBundleGroupBeforeFirstInst() const { + return BundleGroupBeforeFirstInst; + } + void setBundleGroupBeforeFirstInst(bool IsFirst) { + BundleGroupBeforeFirstInst = IsFirst; + } + + bool hasInstructions() const { return HasInstructions; } + void setHasInstructions(bool Value) { HasInstructions = Value; } + + MCSection::FragmentListType &getFragmentList() { return Fragments; } + const MCSection::FragmentListType &getFragmentList() const { + return const_cast<MCSection *>(this)->getFragmentList(); + } + + MCSection::iterator begin(); + MCSection::const_iterator begin() const { + return const_cast<MCSection *>(this)->begin(); + } + + MCSection::iterator end(); + MCSection::const_iterator end() const { + return const_cast<MCSection *>(this)->end(); + } + + MCSection::reverse_iterator rbegin(); + MCSection::const_reverse_iterator rbegin() const { + return const_cast<MCSection *>(this)->rbegin(); + } + + MCSection::reverse_iterator rend(); + MCSection::const_reverse_iterator rend() const { + return const_cast<MCSection *>(this)->rend(); + } + + MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection); + + void dump(); + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, + const MCExpr *Subsection) const = 0; + + /// Return true if a .align directive should use "optimized nops" to fill + /// instead of 0s. + virtual bool UseCodeAlign() const = 0; + + /// Check whether this section is "virtual", that is has no actual object + /// file contents. + virtual bool isVirtualSection() const = 0; +}; + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 0bbf3696686eb..237f6d31fb1b0 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -45,14 +45,15 @@ class MCSymbol; private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - MCSymbol *COMDATSymbol, int Selection, SectionKind K) - : MCSection(SV_COFF, K), SectionName(Section), + MCSymbol *COMDATSymbol, int Selection, SectionKind K, + MCSymbol *Begin) + : MCSection(SV_COFF, K, Begin), SectionName(Section), Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), Selection(Selection) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); } - ~MCSectionCOFF(); + ~MCSectionCOFF() override; public: /// ShouldOmitSectionDirective - Decides whether a '.section' directive @@ -60,12 +61,6 @@ class MCSymbol; bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } - std::string getLabelBeginName() const override { - return SectionName.str() + "_begin"; - } - std::string getLabelEndName() const override { - return SectionName.str() + "_end"; - } unsigned getCharacteristics() const { return Characteristics; } MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; } int getSelection() const { return Selection; } diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 5ec23f1afad21..9efe1022f2957 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -39,6 +39,8 @@ class MCSectionELF : public MCSection { /// below. unsigned Flags; + unsigned UniqueID; + /// EntrySize - The size of each entry in this section. This size only /// makes sense for sections that contain fixed-sized entries. If a /// section does not contain fixed-sized entries 'EntrySize' will be 0. @@ -46,13 +48,18 @@ class MCSectionELF : public MCSection { const MCSymbol *Group; + /// Depending on the type of the section this is sh_link or sh_info. + const MCSectionELF *Associated; + private: friend class MCContext; - MCSectionELF(StringRef Section, unsigned type, unsigned flags, - SectionKind K, unsigned entrySize, const MCSymbol *group) - : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), - EntrySize(entrySize), Group(group) {} - ~MCSectionELF(); + MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, + unsigned entrySize, const MCSymbol *group, unsigned UniqueID, + MCSymbol *Begin, const MCSectionELF *Associated) + : MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type), + Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group), + Associated(Associated) {} + ~MCSectionELF() override; void setSectionName(StringRef Name) { SectionName = Name; } @@ -63,16 +70,6 @@ public: bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } - std::string getLabelBeginName() const override { - if (Group) - return (SectionName.str() + '_' + Group->getName() + "_begin").str(); - return SectionName.str() + "_begin"; - } - std::string getLabelEndName() const override { - if (Group) - return (SectionName.str() + '_' + Group->getName() + "_end").str(); - return SectionName.str() + "_end"; - } unsigned getType() const { return Type; } unsigned getFlags() const { return Flags; } unsigned getEntrySize() const { return EntrySize; } @@ -83,19 +80,14 @@ public: bool UseCodeAlign() const override; bool isVirtualSection() const override; - /// isBaseAddressKnownZero - We know that non-allocatable sections (like - /// debug info) have a base of zero. - bool isBaseAddressKnownZero() const override { - return (getFlags() & ELF::SHF_ALLOC) == 0; - } + bool isUnique() const { return UniqueID != ~0U; } + unsigned getUniqueID() const { return UniqueID; } + + const MCSectionELF *getAssociatedSection() const { return Associated; } static bool classof(const MCSection *S) { return S->getVariant() == SV_ELF; } - - // Return the entry size for sections with fixed-width data. - static unsigned DetermineEntrySize(SectionKind Kind); - }; } // end namespace llvm diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index a5a2089a2974f..97227517c82d6 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -35,8 +35,8 @@ class MCSectionMachO : public MCSection { /// size of stubs, for example. unsigned Reserved2; - MCSectionMachO(StringRef Segment, StringRef Section, - unsigned TAA, unsigned reserved2, SectionKind K); + MCSectionMachO(StringRef Segment, StringRef Section, unsigned TAA, + unsigned reserved2, SectionKind K, MCSymbol *Begin); friend class MCContext; public: @@ -53,14 +53,6 @@ public: return StringRef(SectionName); } - std::string getLabelBeginName() const override { - return StringRef(getSegmentName().str() + getSectionName().str() + "_begin"); - } - - std::string getLabelEndName() const override { - return StringRef(getSegmentName().str() + getSectionName().str() + "_end"); - } - unsigned getTypeAndAttributes() const { return TypeAndAttributes; } unsigned getStubSize() const { return Reserved2; } diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 18855f9cf03d8..957913e934c4a 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -16,12 +16,12 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCWinEH.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/SMLoc.h" #include <string> namespace llvm { @@ -42,7 +42,7 @@ class raw_ostream; class formatted_raw_ostream; class AssemblerConstantPools; -typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; +typedef std::pair<MCSection *, const MCExpr *> MCSectionSubPair; /// Target specific streamer interface. This is used so that targets can /// implement support for target specific assembly directives. @@ -87,35 +87,12 @@ public: virtual void finish(); }; -class AArch64TargetStreamer : public MCTargetStreamer { -public: - AArch64TargetStreamer(MCStreamer &S); - ~AArch64TargetStreamer(); - - void finish() override; - - /// Callback used to implement the ldr= pseudo. - /// Add a new entry to the constant pool for the current section and return an - /// MCExpr that can be used to refer to the constant pool location. - const MCExpr *addConstantPoolEntry(const MCExpr *, unsigned Size); - - /// Callback used to implemnt the .ltorg directive. - /// Emit contents of constant pool for the current section. - void emitCurrentConstantPool(); - - /// Callback used to implement the .inst directive. - virtual void emitInst(uint32_t Inst); - -private: - std::unique_ptr<AssemblerConstantPools> ConstantPools; -}; - // FIXME: declared here because it is used from // lib/CodeGen/AsmPrinter/ARMException.cpp. class ARMTargetStreamer : public MCTargetStreamer { public: ARMTargetStreamer(MCStreamer &S); - ~ARMTargetStreamer(); + ~ARMTargetStreamer() override; virtual void emitFnStart(); virtual void emitFnEnd(); @@ -139,6 +116,7 @@ public: StringRef StringValue = ""); virtual void emitFPU(unsigned FPU); virtual void emitArch(unsigned Arch); + virtual void emitArchExtension(unsigned ArchExt); virtual void emitObjectArch(unsigned Arch); virtual void finishAttributeSection(); virtual void emitInst(uint32_t Inst, char Suffix = '\0'); @@ -162,11 +140,12 @@ private: std::unique_ptr<AssemblerConstantPools> ConstantPools; }; -/// MCStreamer - Streaming machine code generation interface. This interface -/// is intended to provide a programatic interface that is very similar to the -/// level that an assembler .s file provides. It has callbacks to emit bytes, -/// handle directives, etc. The implementation of this interface retains -/// state to know what the current section is etc. +/// \brief Streaming machine code generation interface. +/// +/// This interface is intended to provide a programatic interface that is very +/// similar to the level that an assembler .s file provides. It has callbacks +/// to emit bytes, handle directives, etc. The implementation of this interface +/// retains state to know what the current section is etc. /// /// There are multiple implementations of this interface: one for writing out /// a .s file, and implementations that write out .o files of various formats. @@ -175,8 +154,8 @@ class MCStreamer { MCContext &Context; std::unique_ptr<MCTargetStreamer> TargetStreamer; - MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; - MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; + MCStreamer(const MCStreamer &) = delete; + MCStreamer &operator=(const MCStreamer &) = delete; std::vector<MCDwarfFrameInfo> DwarfFrameInfos; MCDwarfFrameInfo *getCurrentDwarfFrameInfo(); @@ -188,12 +167,12 @@ class MCStreamer { WinEH::FrameInfo *CurrentWinFrameInfo; void EnsureValidWinFrameInfo(); - // SymbolOrdering - Tracks an index to represent the order - // a symbol was emitted in. Zero means we did not emit that symbol. + /// \brief Tracks an index to represent the order a symbol was emitted in. + /// Zero means we did not emit that symbol. DenseMap<const MCSymbol *, unsigned> SymbolOrdering; - /// SectionStack - This is stack of current and previous section - /// values saved by PushSection. + /// \brief This is stack of current and previous section values saved by + /// PushSection. SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; protected: @@ -242,22 +221,24 @@ public: void generateCompactUnwindEncodings(MCAsmBackend *MAB); - /// @name Assembly File Formatting. + /// \name Assembly File Formatting. /// @{ - /// isVerboseAsm - Return true if this streamer supports verbose assembly - /// and if it is enabled. + /// \brief Return true if this streamer supports verbose assembly and if it is + /// enabled. virtual bool isVerboseAsm() const { return false; } - /// hasRawTextSupport - Return true if this asm streamer supports emitting - /// unformatted text to the .s file with EmitRawText. + /// \brief Return true if this asm streamer supports emitting unformatted text + /// to the .s file with EmitRawText. virtual bool hasRawTextSupport() const { return false; } - /// Is the integrated assembler required for this streamer to function + /// \brief Is the integrated assembler required for this streamer to function /// correctly? virtual bool isIntegratedAssemblerRequired() const { return false; } - /// AddComment - Add a comment that can be emitted to the generated .s + /// \brief Add a textual command. + /// + /// Typically for comments that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler /// more readable. This only affects the MCAsmStreamer, and only when /// verbose assembly output is enabled. @@ -266,14 +247,14 @@ public: /// prefix as appropriate. The added comment should not end with a \n. virtual void AddComment(const Twine &T) {} - /// GetCommentOS - Return a raw_ostream that comments can be written to. - /// Unlike AddComment, you are required to terminate comments with \n if you - /// use this method. + /// \brief Return a raw_ostream that comments can be written to. Unlike + /// AddComment, you are required to terminate comments with \n if you use this + /// method. virtual raw_ostream &GetCommentOS(); - /// Print T and prefix it with the comment string (normally #) and optionally - /// a tab. This prints the comment immediately, not at the end of the - /// current line. It is basically a safe version of EmitRawText: since it + /// \brief Print T and prefix it with the comment string (normally #) and + /// optionally a tab. This prints the comment immediately, not at the end of + /// the current line. It is basically a safe version of EmitRawText: since it /// only prints comments, the object streamer ignores it instead of asserting. virtual void emitRawComment(const Twine &T, bool TabPrefix = true); @@ -282,46 +263,43 @@ public: /// @} - /// @name Symbol & Section Management + /// \name Symbol & Section Management /// @{ - /// getCurrentSection - Return the current section that the streamer is - /// emitting code to. + /// \brief Return the current section that the streamer is emitting code to. MCSectionSubPair getCurrentSection() const { if (!SectionStack.empty()) return SectionStack.back().first; return MCSectionSubPair(); } - /// getPreviousSection - Return the previous section that the streamer is - /// emitting code to. + /// \brief Return the previous section that the streamer is emitting code to. MCSectionSubPair getPreviousSection() const { if (!SectionStack.empty()) return SectionStack.back().second; return MCSectionSubPair(); } - /// GetSymbolOrder - Returns an index to represent the order - /// a symbol was emitted in. (zero if we did not emit that symbol) + /// \brief Returns an index to represent the order a symbol was emitted in. + /// (zero if we did not emit that symbol) unsigned GetSymbolOrder(const MCSymbol *Sym) const { return SymbolOrdering.lookup(Sym); } - /// ChangeSection - Update streamer for a new active section. + /// \brief Update streamer for a new active section. /// /// This is called by PopSection and SwitchSection, if the current /// section changes. - virtual void ChangeSection(const MCSection *, const MCExpr *); + virtual void ChangeSection(MCSection *, const MCExpr *); - /// pushSection - Save the current and previous section on the - /// section stack. + /// \brief Save the current and previous section on the section stack. void PushSection() { SectionStack.push_back( std::make_pair(getCurrentSection(), getPreviousSection())); } - /// popSection - Restore the current and previous section from - /// the section stack. Calls ChangeSection as needed. + /// \brief Restore the current and previous section from the section stack. + /// Calls ChangeSection as needed. /// /// Returns false if the stack was empty. bool PopSection() { @@ -343,25 +321,17 @@ public: return true; } - /// SwitchSection - Set the current section where code is being emitted to - /// @p Section. This is required to update CurSection. + /// Set the current section where code is being emitted to \p Section. This + /// is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - virtual void SwitchSection(const MCSection *Section, - const MCExpr *Subsection = nullptr) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) { - SectionStack.back().first = MCSectionSubPair(Section, Subsection); - ChangeSection(Section, Subsection); - } - } + virtual void SwitchSection(MCSection *Section, + const MCExpr *Subsection = nullptr); - /// SwitchSectionNoChange - Set the current section where code is being - /// emitted to @p Section. This is required to update CurSection. This - /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section, + /// \brief Set the current section where code is being emitted to \p Section. + /// This is required to update CurSection. This version does not call + /// ChangeSection. + void SwitchSectionNoChange(MCSection *Section, const MCExpr *Subsection = nullptr) { assert(Section && "Cannot switch to a null section!"); MCSectionSubPair curSection = SectionStack.back().first; @@ -370,21 +340,23 @@ public: SectionStack.back().first = MCSectionSubPair(Section, Subsection); } - /// Create the default sections and set the initial one. + /// \brief Create the default sections and set the initial one. virtual void InitSections(bool NoExecStack); - /// AssignSection - Sets the symbol's section. + MCSymbol *endSection(MCSection *Section); + + /// \brief Sets the symbol's section. /// /// Each emitted symbol will be tracked in the ordering table, /// so we can sort on them later. - void AssignSection(MCSymbol *Symbol, const MCSection *Section); + void AssignSection(MCSymbol *Symbol, MCSection *Section); - /// EmitLabel - Emit a label for @p Symbol into the current section. + /// \brief Emit a label for \p Symbol into the current section. /// /// This corresponds to an assembler statement such as: /// foo: /// - /// @param Symbol - The symbol to emit. A given symbol should only be + /// \param Symbol - The symbol to emit. A given symbol should only be /// emitted as a label once, and symbols emitted as a label should never be /// used in an assignment. // FIXME: These emission are non-const because we mutate the symbol to @@ -393,25 +365,25 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// EmitAssemblerFlag - Note in the output the specified @p Flag. + /// \brief Note in the output the specified \p Flag. virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - /// EmitLinkerOptions - Emit the given list @p Options of strings as linker + /// \brief Emit the given list \p Options of strings as linker /// options into the output. virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {} - /// EmitDataRegion - Note in the output the specified region @p Kind. + /// \brief Note in the output the specified region \p Kind. virtual void EmitDataRegion(MCDataRegionType Kind) {} - /// EmitVersionMin - Specify the MachO minimum deployment target version. + /// \brief Specify the MachO minimum deployment target version. virtual void EmitVersionMin(MCVersionMinType, unsigned Major, unsigned Minor, unsigned Update) {} - /// EmitThumbFunc - Note in the output that the specified @p Func is - /// a Thumb mode function (ARM target only). + /// \brief Note in the output that the specified \p Func is a Thumb mode + /// function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func); - /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. + /// \brief Emit an assignment of \p Value to \p Symbol. /// /// This corresponds to an assembler statement such as: /// symbol = value @@ -420,133 +392,131 @@ public: /// value in the current context. For the assembly streamer, this prints the /// binding into the .s file. /// - /// @param Symbol - The symbol being assigned to. - /// @param Value - The value for the symbol. + /// \param Symbol - The symbol being assigned to. + /// \param Value - The value for the symbol. virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// \brief Emit an weak reference from \p Alias to \p Symbol. /// /// This corresponds to an assembler statement such as: /// .weakref alias, symbol /// - /// @param Alias - The alias that is being created. - /// @param Symbol - The symbol being aliased. + /// \param Alias - The alias that is being created. + /// \param Symbol - The symbol being aliased. virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. + /// \brief Add the given \p Attribute to \p Symbol. virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) = 0; - /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. + /// \brief Set the \p DescValue for the \p Symbol. /// - /// @param Symbol - The symbol to have its n_desc field set. - /// @param DescValue - The value to set into the n_desc field. + /// \param Symbol - The symbol to have its n_desc field set. + /// \param DescValue - The value to set into the n_desc field. virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - /// BeginCOFFSymbolDef - Start emitting COFF symbol definition + /// \brief Start emitting COFF symbol definition /// - /// @param Symbol - The symbol to have its External & Type fields set. + /// \param Symbol - The symbol to have its External & Type fields set. virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); - /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. + /// \brief Emit the storage class of the symbol. /// - /// @param StorageClass - The storage class the symbol should have. + /// \param StorageClass - The storage class the symbol should have. virtual void EmitCOFFSymbolStorageClass(int StorageClass); - /// EmitCOFFSymbolType - Emit the type of the symbol. + /// \brief Emit the type of the symbol. /// - /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + /// \param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) virtual void EmitCOFFSymbolType(int Type); - /// EndCOFFSymbolDef - Marks the end of the symbol definition. + /// \brief Marks the end of the symbol definition. virtual void EndCOFFSymbolDef(); - /// EmitCOFFSectionIndex - Emits a COFF section index. + /// \brief Emits a COFF section index. /// - /// @param Symbol - Symbol the section number relocation should point to. + /// \param Symbol - Symbol the section number relocation should point to. virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol); - /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. + /// \brief Emits a COFF section relative relocation. /// - /// @param Symbol - Symbol the section relative relocation should point to. + /// \param Symbol - Symbol the section relative relocation should point to. virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - /// EmitELFSize - Emit an ELF .size directive. + /// \brief Emit an ELF .size directive. /// /// This corresponds to an assembler statement such as: /// .size symbol, expression - /// virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); /// \brief Emit a Linker Optimization Hint (LOH) directive. /// \param Args - Arguments of the LOH. virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {} - /// EmitCommonSymbol - Emit a common symbol. + /// \brief Emit a common symbol. /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the symbol if + /// \param Symbol - The common symbol to emit. + /// \param Size - The size of the common symbol. + /// \param ByteAlignment - The alignment of the symbol if /// non-zero. This must be a power of 2. virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) = 0; - /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// \brief Emit a local common (.lcomm) symbol. /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the common symbol in bytes. + /// \param Symbol - The common symbol to emit. + /// \param Size - The size of the common symbol. + /// \param ByteAlignment - The alignment of the common symbol in bytes. virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); - /// EmitZerofill - Emit the zerofill section and an optional symbol. + /// \brief Emit the zerofill section and an optional symbol. /// - /// @param Section - The zerofill section to create and or to put the symbol - /// @param Symbol - The zerofill symbol to emit, if non-NULL. - /// @param Size - The size of the zerofill symbol. - /// @param ByteAlignment - The alignment of the zerofill symbol if + /// \param Section - The zerofill section to create and or to put the symbol + /// \param Symbol - The zerofill symbol to emit, if non-NULL. + /// \param Size - The size of the zerofill symbol. + /// \param ByteAlignment - The alignment of the zerofill symbol if /// non-zero. This must be a power of 2 on some targets. - virtual void EmitZerofill(const MCSection *Section, - MCSymbol *Symbol = nullptr, uint64_t Size = 0, - unsigned ByteAlignment = 0) = 0; + virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0) = 0; - /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. + /// \brief Emit a thread local bss (.tbss) symbol. /// - /// @param Section - The thread local common section. - /// @param Symbol - The thread local common symbol to emit. - /// @param Size - The size of the symbol. - /// @param ByteAlignment - The alignment of the thread local common symbol + /// \param Section - The thread local common section. + /// \param Symbol - The thread local common symbol to emit. + /// \param Size - The size of the symbol. + /// \param ByteAlignment - The alignment of the thread local common symbol /// if non-zero. This must be a power of 2 on some targets. - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + virtual void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0); /// @} - /// @name Generating Data + /// \name Generating Data /// @{ - /// EmitBytes - Emit the bytes in \p Data into the output. + /// \brief Emit the bytes in \p Data into the output. /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. virtual void EmitBytes(StringRef Data); - /// EmitValue - Emit the expression @p Value into the output as a native - /// integer of the given @p Size bytes. + /// \brief Emit the expression \p Value into the output as a native + /// integer of the given \p Size bytes. /// /// This is used to implement assembler directives such as .word, .quad, /// etc. /// - /// @param Value - The value to emit. - /// @param Size - The size of the integer (in bytes) to emit. This must + /// \param Value - The value to emit. + /// \param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - /// @param Loc - The location of the expression for error reporting. + /// \param Loc - The location of the expression for error reporting. virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()); void EmitValue(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()); - /// EmitIntValue - Special case of EmitValue that avoids the client having + /// \brief Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. virtual void EmitIntValue(uint64_t Value, unsigned Size); @@ -554,112 +524,119 @@ public: virtual void EmitSLEB128Value(const MCExpr *Value); - /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. + /// \brief Special case of EmitULEB128Value that avoids the client having to + /// pass in a MCExpr for constant integers. void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0); - /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. + /// \brief Special case of EmitSLEB128Value that avoids the client having to + /// pass in a MCExpr for constant integers. void EmitSLEB128IntValue(int64_t Value); - /// EmitSymbolValue - Special case of EmitValue that avoids the client - /// having to pass in a MCExpr for MCSymbols. + /// \brief Special case of EmitValue that avoids the client having to pass in + /// a MCExpr for MCSymbols. void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, bool IsSectionRelative = false); - /// EmitGPRel64Value - Emit the expression @p Value into the output as a - /// gprel64 (64-bit GP relative) value. + /// \brief Emit the expression \p Value into the output as a gprel64 (64-bit + /// GP relative) value. /// /// This is used to implement assembler directives such as .gpdword on /// targets that support them. virtual void EmitGPRel64Value(const MCExpr *Value); - /// EmitGPRel32Value - Emit the expression @p Value into the output as a - /// gprel32 (32-bit GP relative) value. + /// \brief Emit the expression \p Value into the output as a gprel32 (32-bit + /// GP relative) value. /// /// This is used to implement assembler directives such as .gprel32 on /// targets that support them. virtual void EmitGPRel32Value(const MCExpr *Value); - /// EmitFill - Emit NumBytes bytes worth of the value specified by - /// FillValue. This implements directives such as '.space'. + /// \brief Emit NumBytes bytes worth of the value specified by FillValue. + /// This implements directives such as '.space'. virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); /// \brief Emit NumBytes worth of zeros. /// This function properly handles data in virtual sections. virtual void EmitZeros(uint64_t NumBytes); - /// EmitValueToAlignment - Emit some number of copies of @p Value until - /// the byte alignment @p ByteAlignment is reached. + /// \brief Emit some number of copies of \p Value until the byte alignment \p + /// ByteAlignment is reached. /// /// If the number of bytes need to emit for the alignment is not a multiple - /// of @p ValueSize, then the contents of the emitted fill bytes is + /// of \p ValueSize, then the contents of the emitted fill bytes is /// undefined. /// /// This used to implement the .align assembler directive. /// - /// @param ByteAlignment - The alignment to reach. This must be a power of + /// \param ByteAlignment - The alignment to reach. This must be a power of /// two on some targets. - /// @param Value - The value to use when filling bytes. - /// @param ValueSize - The size of the integer (in bytes) to emit for - /// @p Value. This must match a native machine width. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// \param Value - The value to use when filling bytes. + /// \param ValueSize - The size of the integer (in bytes) to emit for + /// \p Value. This must match a native machine width. + /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If /// the alignment cannot be reached in this many bytes, no bytes are /// emitted. virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); - /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment - /// is reached. + /// \brief Emit nops until the byte alignment \p ByteAlignment is reached. /// /// This used to align code where the alignment bytes may be executed. This /// can emit different bytes for different sizes to optimize execution. /// - /// @param ByteAlignment - The alignment to reach. This must be a power of + /// \param ByteAlignment - The alignment to reach. This must be a power of /// two on some targets. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If /// the alignment cannot be reached in this many bytes, no bytes are /// emitted. virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0); - /// EmitValueToOffset - Emit some number of copies of @p Value until the - /// byte offset @p Offset is reached. + /// \brief Emit some number of copies of \p Value until the byte offset \p + /// Offset is reached. /// /// This is used to implement assembler directives such as .org. /// - /// @param Offset - The offset to reach. This may be an expression, but the + /// \param Offset - The offset to reach. This may be an expression, but the /// expression must be associated with the current section. - /// @param Value - The value to use when filling bytes. - /// @return false on success, true if the offset was invalid. + /// \param Value - The value to use when filling bytes. + /// \return false on success, true if the offset was invalid. virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0); /// @} - /// EmitFileDirective - Switch to a new logical file. This is used to - /// implement the '.file "foo.c"' assembler directive. + /// \brief Switch to a new logical file. This is used to implement the '.file + /// "foo.c"' assembler directive. virtual void EmitFileDirective(StringRef Filename); - /// Emit the "identifiers" directive. This implements the + /// \brief Emit the "identifiers" directive. This implements the /// '.ident "version foo"' assembler directive. virtual void EmitIdent(StringRef IdentString) {} - /// EmitDwarfFileDirective - Associate a filename with a specified logical - /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler - /// directive. + /// \brief Associate a filename with a specified logical file number. This + /// implements the DWARF2 '.file 4 "foo.c"' assembler directive. virtual unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, StringRef Filename, unsigned CUID = 0); - /// EmitDwarfLocDirective - This implements the DWARF2 - // '.loc fileno lineno ...' assembler directive. + /// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler + /// directive. virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator, StringRef FileName); + /// Emit the absolute difference between two symbols if possible. + /// + /// \pre Offset of \c Hi is greater than the offset \c Lo. + /// \return true on success. + virtual bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) { + return false; + } + virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID); virtual void EmitCFISections(bool EH, bool Debug); void EmitCFIStartProc(bool IsSimple); @@ -697,8 +674,7 @@ public: virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except); virtual void EmitWinEHHandlerData(); - /// EmitInstruction - Emit the given @p Instruction into the current - /// section. + /// \brief Emit the given \p Instruction into the current section. virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); /// \brief Set the bundle alignment mode from now on in the section. @@ -715,29 +691,28 @@ public: /// \brief Ends a bundle-locked group. virtual void EmitBundleUnlock(); - /// EmitRawText - If this file is backed by a assembly streamer, this dumps - /// the specified string in the output .s file. This capability is - /// indicated by the hasRawTextSupport() predicate. By default this aborts. + /// \brief If this file is backed by a assembly streamer, this dumps the + /// specified string in the output .s file. This capability is indicated by + /// the hasRawTextSupport() predicate. By default this aborts. void EmitRawText(const Twine &String); - /// Flush - Causes any cached state to be written out. + /// \brief Causes any cached state to be written out. virtual void Flush() {} - /// FinishImpl - Streamer specific finalization. + /// \brief Streamer specific finalization. virtual void FinishImpl(); - /// Finish - Finish emission of machine code. + /// \brief Finish emission of machine code. void Finish(); - virtual bool mayHaveInstructions() const { return true; } + virtual bool mayHaveInstructions(MCSection &Sec) const { return true; } }; -/// createNullStreamer - Create a dummy machine code streamer, which does -/// nothing. This is useful for timing the assembler front end. +/// Create a dummy machine code streamer, which does nothing. This is useful for +/// timing the assembler front end. MCStreamer *createNullStreamer(MCContext &Ctx); -/// createAsmStreamer - Create a machine code streamer which will print out -/// assembly for the native target, suitable for compiling with a native -/// assembler. +/// Create a machine code streamer which will print out assembly for the native +/// target, suitable for compiling with a native assembler. /// /// \param InstPrint - If given, the instruction printer to use. If not given /// the MCInst representation will be printed. This method takes ownership of @@ -752,26 +727,11 @@ MCStreamer *createNullStreamer(MCContext &Ctx); /// /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. -MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, +MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); - -/// createMachOStreamer - Create a machine code streamer which will generate -/// Mach-O format object files. -/// -/// Takes ownership of \p TAB and \p CE. -MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false, - bool LabelSections = false); - -/// createELFStreamer - Create a machine code streamer which will generate -/// ELF format object files. -MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll); - } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 3f38bd59a5766..1778a6d13fb86 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -28,6 +28,7 @@ class StringRef; /// class MCSubtargetInfo { std::string TargetTriple; // Target triple + std::string CPU; // CPU being targeted. ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions @@ -41,7 +42,7 @@ class MCSubtargetInfo { const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles const unsigned *ForwardingPaths; // Forwarding paths - uint64_t FeatureBits; // Feature bits for current CPU + FS + FeatureBitset FeatureBits; // Feature bits for current CPU + FS public: void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS, @@ -59,15 +60,20 @@ public: return TargetTriple; } + /// getCPU - Return the CPU string. + StringRef getCPU() const { + return CPU; + } + /// getFeatureBits - Return the feature bits. /// - uint64_t getFeatureBits() const { + const FeatureBitset& getFeatureBits() const { return FeatureBits; } /// setFeatureBits - Set the feature bits. /// - void setFeatureBits(uint64_t FeatureBits_) { FeatureBits = FeatureBits_; } + void setFeatureBits(FeatureBitset& FeatureBits_) { FeatureBits = FeatureBits_; } /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with /// feature string). Recompute feature bits and scheduling model. @@ -78,11 +84,15 @@ public: /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. - uint64_t ToggleFeature(uint64_t FB); + FeatureBitset ToggleFeature(uint64_t FB); /// ToggleFeature - Toggle a feature and returns the re-computed feature - /// bits. This version will also change all implied bits. - uint64_t ToggleFeature(StringRef FS); + /// bits. This version does not change the implied bits. + FeatureBitset ToggleFeature(const FeatureBitset& FB); + + /// ToggleFeature - Toggle a set of features and returns the re-computed + /// feature bits. This version will also change all implied bits. + FeatureBitset ToggleFeature(StringRef FS); /// getSchedModelForCPU - Get the machine model of a CPU. /// diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 47a8789d463b7..cf99c919281e2 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -14,168 +14,298 @@ #ifndef LLVM_MC_MCSYMBOL_H #define LLVM_MC_MCSYMBOL_H -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/MC/MCExpr.h" #include "llvm/Support/Compiler.h" namespace llvm { - class MCExpr; - class MCSection; - class MCContext; - class raw_ostream; - - /// MCSymbol - Instances of this class represent a symbol name in the MC file, - /// and MCSymbols are created and unique'd by the MCContext class. MCSymbols - /// should only be constructed with valid names for the object file. +class MCExpr; +class MCSymbol; +class MCFragment; +class MCSection; +class MCContext; +class raw_ostream; + +// TODO: Merge completely with MCSymbol. +class MCSymbolData { + /// Fragment - The fragment this symbol's value is relative to, if any. Also + /// stores if this symbol is visible outside this translation unit (bit 0) or + /// if it is private extern (bit 1). + PointerIntPair<MCFragment *, 2> Fragment; + + union { + /// Offset - The offset to apply to the fragment address to form this + /// symbol's value. + uint64_t Offset; + + /// CommonSize - The size of the symbol, if it is 'common'. + uint64_t CommonSize; + }; + + /// SymbolSize - An expression describing how to calculate the size of + /// a symbol. If a symbol has no size this field will be NULL. + const MCExpr *SymbolSize = nullptr; + + /// CommonAlign - The alignment of the symbol, if it is 'common', or -1. + // + // FIXME: Pack this in with other fields? + unsigned CommonAlign = -1U; + + /// Flags - The Flags field is used by object file implementations to store + /// additional per symbol information which is not easily classified. + uint32_t Flags = 0; + +public: + MCSymbolData() { Offset = 0; } + + MCFragment *getFragment() const { return Fragment.getPointer(); } + void setFragment(MCFragment *Value) { Fragment.setPointer(Value); } + + uint64_t getOffset() const { + assert(!isCommon()); + return Offset; + } + void setOffset(uint64_t Value) { + assert(!isCommon()); + Offset = Value; + } + + /// @} + /// \name Symbol Attributes + /// @{ + + bool isExternal() const { return Fragment.getInt() & 1; } + void setExternal(bool Value) { + Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value)); + } + + bool isPrivateExtern() const { return Fragment.getInt() & 2; } + void setPrivateExtern(bool Value) { + Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1)); + } + + /// isCommon - Is this a 'common' symbol. + bool isCommon() const { return CommonAlign != -1U; } + + /// setCommon - Mark this symbol as being 'common'. /// - /// If the symbol is defined/emitted into the current translation unit, the - /// Section member is set to indicate what section it lives in. Otherwise, if - /// it is a reference to an external entity, it has a null section. - class MCSymbol { - // Special sentinal value for the absolute pseudo section. - // - // FIXME: Use a PointerInt wrapper for this? - static const MCSection *AbsolutePseudoSection; - - /// Name - The name of the symbol. The referred-to string data is actually - /// held by the StringMap that lives in MCContext. - StringRef Name; - - /// Section - The section the symbol is defined in. This is null for - /// undefined symbols, and the special AbsolutePseudoSection value for - /// absolute symbols. - const MCSection *Section; - - /// Value - If non-null, the value for a variable symbol. - const MCExpr *Value; - - /// IsTemporary - True if this is an assembler temporary label, which - /// typically does not survive in the .o file's symbol table. Usually - /// "Lfoo" or ".foo". - unsigned IsTemporary : 1; - - /// \brief True if this symbol can be redefined. - unsigned IsRedefinable : 1; - - /// IsUsed - True if this symbol has been used. - mutable unsigned IsUsed : 1; - - private: // MCContext creates and uniques these. - friend class MCExpr; - friend class MCContext; - MCSymbol(StringRef name, bool isTemporary) - : Name(name), Section(nullptr), Value(nullptr), - IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {} - - MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION; - void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION; - public: - /// getName - Get the symbol name. - StringRef getName() const { return Name; } - - /// @name Accessors - /// @{ - - /// isTemporary - Check if this is an assembler temporary symbol. - bool isTemporary() const { return IsTemporary; } - - /// isUsed - Check if this is used. - bool isUsed() const { return IsUsed; } - void setUsed(bool Value) const { IsUsed = Value; } - - /// \brief Check if this symbol is redefinable. - bool isRedefinable() const { return IsRedefinable; } - /// \brief Mark this symbol as redefinable. - void setRedefinable(bool Value) { IsRedefinable = Value; } - /// \brief Prepare this symbol to be redefined. - void redefineIfPossible() { - if (IsRedefinable) { - Value = nullptr; - Section = nullptr; - IsRedefinable = false; - } - } + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + void setCommon(uint64_t Size, unsigned Align) { + assert(getOffset() == 0); + CommonSize = Size; + CommonAlign = Align; + } - /// @} - /// @name Associated Sections - /// @{ + /// getCommonSize - Return the size of a 'common' symbol. + uint64_t getCommonSize() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonSize; + } - /// isDefined - Check if this symbol is defined (i.e., it has an address). - /// - /// Defined symbols are either absolute or in some section. - bool isDefined() const { - return Section != nullptr; - } + void setSize(const MCExpr *SS) { SymbolSize = SS; } - /// isInSection - Check if this symbol is defined in some section (i.e., it - /// is defined but not absolute). - bool isInSection() const { - return isDefined() && !isAbsolute(); - } + const MCExpr *getSize() const { return SymbolSize; } - /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). - bool isUndefined() const { - return !isDefined(); - } + /// getCommonAlignment - Return the alignment of a 'common' symbol. + unsigned getCommonAlignment() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonAlign; + } - /// isAbsolute - Check if this is an absolute symbol. - bool isAbsolute() const { - return Section == AbsolutePseudoSection; - } + /// getFlags - Get the (implementation defined) symbol flags. + uint32_t getFlags() const { return Flags; } - /// getSection - Get the section associated with a defined, non-absolute - /// symbol. - const MCSection &getSection() const { - assert(isInSection() && "Invalid accessor!"); - return *Section; - } + /// setFlags - Set the (implementation defined) symbol flags. + void setFlags(uint32_t Value) { Flags = Value; } - /// setSection - Mark the symbol as defined in the section \p S. - void setSection(const MCSection &S) { Section = &S; } + /// modifyFlags - Modify the flags via a mask + void modifyFlags(uint32_t Value, uint32_t Mask) { + Flags = (Flags & ~Mask) | Value; + } + + /// @} + + void dump() const; +}; + +/// MCSymbol - Instances of this class represent a symbol name in the MC file, +/// and MCSymbols are created and uniqued by the MCContext class. MCSymbols +/// should only be constructed with valid names for the object file. +/// +/// If the symbol is defined/emitted into the current translation unit, the +/// Section member is set to indicate what section it lives in. Otherwise, if +/// it is a reference to an external entity, it has a null section. +class MCSymbol { + // Special sentinal value for the absolute pseudo section. + // + // FIXME: Use a PointerInt wrapper for this? + static MCSection *AbsolutePseudoSection; + + /// Name - The name of the symbol. The referred-to string data is actually + /// held by the StringMap that lives in MCContext. + const StringMapEntry<bool> *Name; + + /// The section the symbol is defined in. This is null for undefined symbols, + /// and the special AbsolutePseudoSection value for absolute symbols. If this + /// is a variable symbol, this caches the variable value's section. + mutable MCSection *Section; + + /// Value - If non-null, the value for a variable symbol. + const MCExpr *Value; + + /// IsTemporary - True if this is an assembler temporary label, which + /// typically does not survive in the .o file's symbol table. Usually + /// "Lfoo" or ".foo". + unsigned IsTemporary : 1; + + /// \brief True if this symbol can be redefined. + unsigned IsRedefinable : 1; + + /// IsUsed - True if this symbol has been used. + mutable unsigned IsUsed : 1; + + mutable bool HasData : 1; + + /// Index field, for use by the object file implementation. + mutable uint64_t Index : 60; + + mutable MCSymbolData Data; + +private: // MCContext creates and uniques these. + friend class MCExpr; + friend class MCContext; + MCSymbol(const StringMapEntry<bool> *Name, bool isTemporary) + : Name(Name), Section(nullptr), Value(nullptr), IsTemporary(isTemporary), + IsRedefinable(false), IsUsed(false), HasData(false), Index(0) {} + + MCSymbol(const MCSymbol &) = delete; + void operator=(const MCSymbol &) = delete; + MCSection *getSectionPtr() const { + if (Section || !Value) + return Section; + return Section = Value->FindAssociatedSection(); + } + +public: + /// getName - Get the symbol name. + StringRef getName() const { return Name ? Name->first() : ""; } + + bool hasData() const { return HasData; } + + /// Get associated symbol data. + MCSymbolData &getData() const { + assert(HasData && "Missing symbol data!"); + return Data; + } - /// setUndefined - Mark the symbol as undefined. - void setUndefined() { + /// Initialize symbol data. + /// + /// Nothing really to do here, but this is enables an assertion that \a + /// MCAssembler::getOrCreateSymbolData() has actually been called before + /// anyone calls \a getData(). + void initializeData() const { HasData = true; } + + /// \name Accessors + /// @{ + + /// isTemporary - Check if this is an assembler temporary symbol. + bool isTemporary() const { return IsTemporary; } + + /// isUsed - Check if this is used. + bool isUsed() const { return IsUsed; } + void setUsed(bool Value) const { IsUsed = Value; } + + /// \brief Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// \brief Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// \brief Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + Value = nullptr; Section = nullptr; + IsRedefinable = false; } + } - /// setAbsolute - Mark the symbol as absolute. - void setAbsolute() { Section = AbsolutePseudoSection; } + /// @} + /// \name Associated Sections + /// @{ - /// @} - /// @name Variable Symbols - /// @{ + /// isDefined - Check if this symbol is defined (i.e., it has an address). + /// + /// Defined symbols are either absolute or in some section. + bool isDefined() const { return getSectionPtr() != nullptr; } - /// isVariable - Check if this is a variable symbol. - bool isVariable() const { - return Value != nullptr; - } + /// isInSection - Check if this symbol is defined in some section (i.e., it + /// is defined but not absolute). + bool isInSection() const { return isDefined() && !isAbsolute(); } - /// getVariableValue() - Get the value for variable symbols. - const MCExpr *getVariableValue() const { - assert(isVariable() && "Invalid accessor!"); - IsUsed = true; - return Value; - } + /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). + bool isUndefined() const { return !isDefined(); } - // AliasedSymbol() - If this is an alias (a = b), return the symbol - // we ultimately point to. For a non-alias, this just returns the symbol - // itself. - const MCSymbol &AliasedSymbol() const; + /// isAbsolute - Check if this is an absolute symbol. + bool isAbsolute() const { return getSectionPtr() == AbsolutePseudoSection; } - void setVariableValue(const MCExpr *Value); + /// Get the section associated with a defined, non-absolute symbol. + MCSection &getSection() const { + assert(isInSection() && "Invalid accessor!"); + return *getSectionPtr(); + } - /// @} + /// Mark the symbol as defined in the section \p S. + void setSection(MCSection &S) { + assert(!isVariable() && "Cannot set section of variable"); + Section = &S; + } - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS) const; + /// setUndefined - Mark the symbol as undefined. + void setUndefined() { Section = nullptr; } - /// dump - Print the value to stderr. - void dump() const; - }; + /// @} + /// \name Variable Symbols + /// @{ + + /// isVariable - Check if this is a variable symbol. + bool isVariable() const { return Value != nullptr; } + + /// getVariableValue() - Get the value for variable symbols. + const MCExpr *getVariableValue() const { + assert(isVariable() && "Invalid accessor!"); + IsUsed = true; + return Value; + } + + void setVariableValue(const MCExpr *Value); - inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { - Sym.print(OS); - return OS; + /// @} + + /// Get the (implementation defined) index. + uint64_t getIndex() const { + assert(HasData && "Uninitialized symbol data"); + return Index; + } + + /// Set the (implementation defined) index. + void setIndex(uint64_t Value) const { + assert(HasData && "Uninitialized symbol data"); + assert(!(Value >> 60) && "Not enough bits for value"); + Index = Value; } + + /// print - Print the value to the stream \p OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { + Sym.print(OS); + return OS; +} } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h index cbbb591f1b80c..2ef17673f091e 100644 --- a/include/llvm/MC/MCSymbolizer.h +++ b/include/llvm/MC/MCSymbolizer.h @@ -38,8 +38,8 @@ class raw_ostream; /// operands are actually symbolizable, and in what way. I don't think this /// information exists right now. class MCSymbolizer { - MCSymbolizer(const MCSymbolizer &) LLVM_DELETED_FUNCTION; - void operator=(const MCSymbolizer &) LLVM_DELETED_FUNCTION; + MCSymbolizer(const MCSymbolizer &) = delete; + void operator=(const MCSymbolizer &) = delete; protected: MCContext &Ctx; @@ -59,14 +59,14 @@ public: /// represent this immediate in a more understandable way, for instance as a /// symbol or an offset from a symbol. Relocations can also be used to enrich /// the symbolic expression. - /// @param Inst - The MCInst where to insert the symbolic operand. - /// @param cStream - Stream to print comments and annotations on. - /// @param Value - Operand value, pc-adjusted by the caller if necessary. - /// @param Address - Load address of the instruction. - /// @param IsBranch - Is the instruction a branch? - /// @param Offset - Byte offset of the operand inside the inst. - /// @param InstSize - Size of the instruction in bytes. - /// @return Whether a symbolic operand was added. + /// \param Inst - The MCInst where to insert the symbolic operand. + /// \param cStream - Stream to print comments and annotations on. + /// \param Value - Operand value, pc-adjusted by the caller if necessary. + /// \param Address - Load address of the instruction. + /// \param IsBranch - Is the instruction a branch? + /// \param Offset - Byte offset of the operand inside the inst. + /// \param InstSize - Size of the instruction in bytes. + /// \return Whether a symbolic operand was added. virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, int64_t Value, uint64_t Address, bool IsBranch, uint64_t Offset, diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index ea71d1f433a45..36db3914f0174 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -75,8 +75,6 @@ struct ParseInstructionInfo { ParseInstructionInfo() : AsmRewrites(nullptr) {} ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites) : AsmRewrites(rewrites) {} - - ~ParseInstructionInfo() {} }; /// MCTargetAsmParser - Generic interface to target specific assembly parsers. @@ -91,8 +89,8 @@ public: }; private: - MCTargetAsmParser(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION; - void operator=(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION; + MCTargetAsmParser(const MCTargetAsmParser &) = delete; + void operator=(const MCTargetAsmParser &) = delete; protected: // Can only create subclasses. MCTargetAsmParser(); @@ -110,7 +108,7 @@ protected: // Can only create subclasses. MCTargetOptions MCOptions; public: - virtual ~MCTargetAsmParser(); + ~MCTargetAsmParser() override; uint64_t getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index dd86979690cfc..6bdf43685f211 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -23,10 +23,11 @@ namespace llvm { class MCAsmInfo; class raw_ostream; -/// MCValue - This represents an "assembler immediate". In its most -/// general form, this can hold ":Kind:(SymbolA - SymbolB + imm64)". -/// Not all targets supports relocations of this general form, but we -/// need to represent this anyway. +/// \brief This represents an "assembler immediate". +/// +/// In its most general form, this can hold ":Kind:(SymbolA - SymbolB + +/// imm64)". Not all targets supports relocations of this general form, but we +/// need to represent this anyway. /// /// In general both SymbolA and SymbolB will also have a modifier /// analogous to the top-level Kind. Current targets are not expected @@ -51,13 +52,13 @@ public: const MCSymbolRefExpr *getSymB() const { return SymB; } uint32_t getRefKind() const { return RefKind; } - /// isAbsolute - Is this an absolute (as opposed to relocatable) value. + /// \brief Is this an absolute (as opposed to relocatable) value. bool isAbsolute() const { return !SymA && !SymB; } - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + /// \brief Print the value to the stream \p OS. + void print(raw_ostream &OS) const; - /// dump - Print the value to stderr. + /// \brief Print the value to stderr. void dump() const; MCSymbolRefExpr::VariantKind getAccessVariant() const; diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index dad7bb597039b..e2e95c7df7101 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -11,10 +11,12 @@ #define LLVM_MC_MCWINCOFFOBJECTWRITER_H namespace llvm { - class MCFixup; - class MCObjectWriter; - class MCValue; - class raw_ostream; +class MCAsmBackend; +class MCFixup; +class MCObjectWriter; +class MCValue; +class raw_ostream; +class raw_pwrite_stream; class MCWinCOFFObjectTargetWriter { virtual void anchor(); @@ -27,9 +29,9 @@ namespace llvm { virtual ~MCWinCOFFObjectTargetWriter() {} unsigned getMachine() const { return Machine; } - virtual unsigned getRelocType(const MCValue &Target, - const MCFixup &Fixup, - bool IsCrossSection) const = 0; + virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsCrossSection, + const MCAsmBackend &MAB) const = 0; virtual bool recordRelocation(const MCFixup &) const { return true; } }; @@ -39,7 +41,7 @@ namespace llvm { /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, - raw_ostream &OS); + raw_pwrite_stream &OS); } // End llvm namespace #endif diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index 57a75cec22047..6a83e02298ffc 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -24,11 +24,12 @@ class MCSubtargetInfo; class MCSymbol; class StringRef; class raw_ostream; +class raw_pwrite_stream; class MCWinCOFFStreamer : public MCObjectStreamer { public: MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE, - raw_ostream &OS); + raw_pwrite_stream &OS); /// state management void reset() override { @@ -56,9 +57,9 @@ public: unsigned ByteAlignment) override; void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitFileDirective(StringRef Filename) override; void EmitIdent(StringRef IdentString) override; diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h index 05b58c753b661..723d7a397c496 100644 --- a/include/llvm/MC/MCWinEH.h +++ b/include/llvm/MC/MCWinEH.h @@ -65,10 +65,10 @@ struct FrameInfo { class UnwindEmitter { public: - static const MCSection *getPDataSection(const MCSymbol *Function, - MCContext &Context); - static const MCSection *getXDataSection(const MCSymbol *Function, - MCContext &Context); + static MCSection *getPDataSection(const MCSymbol *Function, + MCContext &Context); + static MCSection *getXDataSection(const MCSymbol *Function, + MCContext &Context); virtual ~UnwindEmitter() { } diff --git a/include/llvm/MC/SectionKind.h b/include/llvm/MC/SectionKind.h index 85a91c6b16988..9e8b68f4340c9 100644 --- a/include/llvm/MC/SectionKind.h +++ b/include/llvm/MC/SectionKind.h @@ -55,7 +55,6 @@ class SectionKind { /// MergeableConst - These are sections for merging fixed-length /// constants together. For example, this can be used to unique /// constant pool entries etc. - MergeableConst, /// MergeableConst4 - This is a section used by 4-byte constants, /// for example, floats. @@ -151,8 +150,8 @@ public: bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; } bool isMergeableConst() const { - return K == MergeableConst || K == MergeableConst4 || - K == MergeableConst8 || K == MergeableConst16; + return K == MergeableConst4 || K == MergeableConst8 || + K == MergeableConst16; } bool isMergeableConst4() const { return K == MergeableConst4; } bool isMergeableConst8() const { return K == MergeableConst8; } @@ -216,7 +215,6 @@ public: static SectionKind getMergeable4ByteCString() { return get(Mergeable4ByteCString); } - static SectionKind getMergeableConst() { return get(MergeableConst); } static SectionKind getMergeableConst4() { return get(MergeableConst4); } static SectionKind getMergeableConst8() { return get(MergeableConst8); } static SectionKind getMergeableConst16() { return get(MergeableConst16); } diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index bfecb8ba6ab0a..6a631ffe79bd3 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -21,11 +21,29 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" +#include <bitset> namespace llvm { class raw_ostream; class StringRef; +// A container class for subtarget features. +// This is convenient because std::bitset does not have a constructor +// with an initializer list of set bits. +const unsigned MAX_SUBTARGET_FEATURES = 64; +class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> { +public: + // Cannot inherit constructors because it's not supported by VC++.. + FeatureBitset() : bitset() {} + + FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {} + + FeatureBitset(std::initializer_list<unsigned> Init) : bitset() { + for (auto I = Init.begin() , E = Init.end(); I != E; ++I) + set(*I); + } +}; + //===----------------------------------------------------------------------===// /// /// SubtargetFeatureKV - Used to provide key value pairs for feature and @@ -34,8 +52,8 @@ namespace llvm { struct SubtargetFeatureKV { const char *Key; // K-V key string const char *Desc; // Help descriptor - uint64_t Value; // K-V integer value - uint64_t Implies; // K-V bit mask + FeatureBitset Value; // K-V integer value + FeatureBitset Implies; // K-V bit mask // Compare routine for std::lower_bound bool operator<(StringRef S) const { @@ -78,15 +96,15 @@ public: std::string getString() const; /// Adding Features. - void AddFeature(StringRef String); + void AddFeature(StringRef String, bool Enable = true); /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. - uint64_t ToggleFeature(uint64_t Bits, StringRef String, + FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String, ArrayRef<SubtargetFeatureKV> FeatureTable); /// Get feature bits of a CPU. - uint64_t getFeatureBits(StringRef CPU, + FeatureBitset getFeatureBits(StringRef CPU, ArrayRef<SubtargetFeatureKV> CPUTable, ArrayRef<SubtargetFeatureKV> FeatureTable); |