diff options
Diffstat (limited to 'include/llvm/MC')
25 files changed, 590 insertions, 157 deletions
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 971e9354da8c..3261c483e0d8 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -165,6 +165,10 @@ protected: /// instead. bool UseDataRegionDirectives = false; + /// True if .align is to be used for alignment. Only power-of-two + /// alignment is supported. + bool UseDotAlignForAlignment = false; + //===--- Data Emission Directives -------------------------------------===// /// This should be set to the directive used to get some number of zero bytes @@ -313,6 +317,10 @@ protected: /// Defaults to false. bool HasLinkOnceDirective = false; + /// True if we have a .lglobl directive, which is used to emit the information + /// of a static symbol into the symbol table. Defaults to false. + bool HasDotLGloblDirective = false; + /// This attribute, if not MCSA_Invalid, is used to declare a symbol as having /// hidden visibility. Defaults to MCSA_Hidden. MCSymbolAttr HiddenVisibilityAttr = MCSA_Hidden; @@ -388,6 +396,9 @@ protected: // %hi(), and similar unary operators. bool HasMipsExpressions = false; + // If true, emit function descriptor symbol on AIX. + bool NeedsFunctionDescriptors = false; + public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); @@ -520,6 +531,10 @@ public: return UseDataRegionDirectives; } + bool useDotAlignForAlignment() const { + return UseDotAlignForAlignment; + } + const char *getZeroDirective() const { return ZeroDirective; } const char *getAsciiDirective() const { return AsciiDirective; } const char *getAscizDirective() const { return AscizDirective; } @@ -557,6 +572,8 @@ public: bool hasLinkOnceDirective() const { return HasLinkOnceDirective; } + bool hasDotLGloblDirective() const { return HasDotLGloblDirective; } + MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr; } MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { @@ -639,6 +656,7 @@ public: bool canRelaxRelocations() const { return RelaxELFRelocations; } void setRelaxELFRelocations(bool V) { RelaxELFRelocations = V; } bool hasMipsExpressions() const { return HasMipsExpressions; } + bool needsFunctionDescriptors() const { return NeedsFunctionDescriptors; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCAsmInfoXCOFF.h b/include/llvm/MC/MCAsmInfoXCOFF.h index 2a72ba7398a7..4a3bacc954e0 100644 --- a/include/llvm/MC/MCAsmInfoXCOFF.h +++ b/include/llvm/MC/MCAsmInfoXCOFF.h @@ -18,6 +18,11 @@ class MCAsmInfoXCOFF : public MCAsmInfo { protected: MCAsmInfoXCOFF(); + +public: + // Return true only when the identifier Name does not need quotes to be + // syntactically correct for XCOFF. + bool isValidUnquotedName(StringRef Name) const override; }; } // end namespace llvm diff --git a/include/llvm/MC/MCAsmMacro.h b/include/llvm/MC/MCAsmMacro.h index 364d3b5f3666..7eecce0faf64 100644 --- a/include/llvm/MC/MCAsmMacro.h +++ b/include/llvm/MC/MCAsmMacro.h @@ -124,7 +124,6 @@ public: } void dump(raw_ostream &OS) const; - void dump() const { dump(dbgs()); } }; struct MCAsmMacroParameter { @@ -133,10 +132,10 @@ struct MCAsmMacroParameter { bool Required = false; bool Vararg = false; - MCAsmMacroParameter() = default; - +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const { dump(dbgs()); } - void dump(raw_ostream &OS) const; + LLVM_DUMP_METHOD void dump(raw_ostream &OS) const; +#endif }; typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters; @@ -149,8 +148,10 @@ public: MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P) : Name(N), Body(B), Parameters(std::move(P)) {} +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const { dump(dbgs()); } - void dump(raw_ostream &OS) const; + LLVM_DUMP_METHOD void dump(raw_ostream &OS) const; +#endif }; } // namespace llvm diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 5c2124cc0d15..b925f3218883 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -22,6 +22,7 @@ #include "llvm/MC/MCAsmMacro.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" @@ -112,6 +113,9 @@ namespace llvm { /// number of section symbols with the same name). StringMap<bool, BumpPtrAllocator &> UsedNames; + /// Keeps track of labels that are used in inline assembly. + SymbolTable InlineAsmUsedLabelNames; + /// The next ID to dole out to an unnamed assembler temporary symbol with /// a given prefix. StringMap<unsigned> NextID; @@ -275,6 +279,8 @@ namespace llvm { /// Do automatic reset in destructor bool AutoReset; + MCTargetOptions const *TargetOptions; + bool HadError = false; MCSymbol *createSymbolImpl(const StringMapEntry<bool> *Name, @@ -298,7 +304,9 @@ namespace llvm { public: explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI, const MCObjectFileInfo *MOFI, - const SourceMgr *Mgr = nullptr, bool DoAutoReset = true); + const SourceMgr *Mgr = nullptr, + MCTargetOptions const *TargetOpts = nullptr, + bool DoAutoReset = true); MCContext(const MCContext &) = delete; MCContext &operator=(const MCContext &) = delete; ~MCContext(); @@ -377,6 +385,16 @@ namespace llvm { /// APIs. const SymbolTable &getSymbols() const { return Symbols; } + /// isInlineAsmLabel - Return true if the name is a label referenced in + /// inline assembly. + MCSymbol *getInlineAsmLabel(StringRef Name) const { + return InlineAsmUsedLabelNames.lookup(Name); + } + + /// registerInlineAsmLabel - Records that the name is a label referenced in + /// inline assembly. + void registerInlineAsmLabel(MCSymbol *Sym); + /// @} /// \name Section Management @@ -490,6 +508,8 @@ namespace llvm { MCSectionXCOFF *getXCOFFSection(StringRef Section, XCOFF::StorageMappingClass MappingClass, + XCOFF::SymbolType CSectType, + XCOFF::StorageClass StorageClass, SectionKind K, const char *BeginSymName = nullptr); @@ -659,6 +679,7 @@ namespace llvm { bool hadError() { return HadError; } void reportError(SMLoc L, const Twine &Msg); + void reportWarning(SMLoc L, const Twine &Msg); // 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. diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h index 4029264c2026..ea79e68674e5 100644 --- a/include/llvm/MC/MCDirectives.h +++ b/include/llvm/MC/MCDirectives.h @@ -28,6 +28,7 @@ enum MCSymbolAttr { MCSA_ELF_TypeNoType, ///< .type _foo, STT_NOTYPE # aka @notype MCSA_ELF_TypeGnuUniqueObject, /// .type _foo, @gnu_unique_object MCSA_Global, ///< .globl + MCSA_LGlobal, ///< .lglobl (XCOFF) MCSA_Hidden, ///< .hidden (ELF) MCSA_IndirectSymbol, ///< .indirect_symbol (MachO) MCSA_Internal, ///< .internal (ELF) diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 1a37aafd0654..a33b4b31bb06 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -629,7 +629,8 @@ public: static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH); static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta); static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, - raw_ostream &OS); + raw_ostream &OS, uint32_t *Offset = nullptr, + uint32_t *Size = nullptr); }; } // end namespace llvm diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index fb23c0114c76..eb2786501f84 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -48,10 +48,6 @@ private: bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, - const SectionAddrMap *Addrs) const; - - bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, - const MCAsmLayout *Layout, const SectionAddrMap *Addrs, bool InSet) const; protected: @@ -136,7 +132,7 @@ class MCConstantExpr : public MCExpr { int64_t Value; bool PrintInHex = false; - MCConstantExpr(int64_t Value) + explicit MCConstantExpr(int64_t Value) : MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {} MCConstantExpr(int64_t Value, bool PrintInHex) @@ -239,6 +235,8 @@ public: VK_PPC_TOC_LO, // symbol@toc@l VK_PPC_TOC_HI, // symbol@toc@h VK_PPC_TOC_HA, // symbol@toc@ha + VK_PPC_U, // symbol@u + VK_PPC_L, // symbol@l VK_PPC_DTPMOD, // symbol@dtpmod VK_PPC_TPREL_LO, // symbol@tprel@l VK_PPC_TPREL_HI, // symbol@tprel@h diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index accffb7f2247..29e321e2354c 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -20,35 +20,38 @@ class MCExpr; /// Extensible enumeration to represent the type of a fixup. enum MCFixupKind { - FK_NONE = 0, ///< A no-op fixup. - FK_Data_1, ///< A one-byte fixup. - FK_Data_2, ///< A two-byte fixup. - FK_Data_4, ///< A four-byte fixup. - FK_Data_8, ///< A eight-byte fixup. - FK_PCRel_1, ///< A one-byte pc relative fixup. - FK_PCRel_2, ///< A two-byte pc relative fixup. - FK_PCRel_4, ///< A four-byte pc relative fixup. - FK_PCRel_8, ///< A eight-byte pc relative fixup. - FK_GPRel_1, ///< A one-byte gp relative fixup. - FK_GPRel_2, ///< A two-byte gp relative fixup. - FK_GPRel_4, ///< A four-byte gp relative fixup. - FK_GPRel_8, ///< A eight-byte gp relative fixup. - FK_DTPRel_4, ///< A four-byte dtp relative fixup. - FK_DTPRel_8, ///< A eight-byte dtp relative fixup. - FK_TPRel_4, ///< A four-byte tp relative fixup. - FK_TPRel_8, ///< A eight-byte tp relative fixup. - FK_SecRel_1, ///< A one-byte section relative fixup. - FK_SecRel_2, ///< A two-byte section relative fixup. - FK_SecRel_4, ///< A four-byte section relative fixup. - FK_SecRel_8, ///< A eight-byte section relative fixup. - FK_Data_Add_1, ///< A one-byte add fixup. - FK_Data_Add_2, ///< A two-byte add fixup. - FK_Data_Add_4, ///< A four-byte add fixup. - FK_Data_Add_8, ///< A eight-byte add fixup. - FK_Data_Sub_1, ///< A one-byte sub fixup. - FK_Data_Sub_2, ///< A two-byte sub fixup. - FK_Data_Sub_4, ///< A four-byte sub fixup. - FK_Data_Sub_8, ///< A eight-byte sub fixup. + FK_NONE = 0, ///< A no-op fixup. + FK_Data_1, ///< A one-byte fixup. + FK_Data_2, ///< A two-byte fixup. + FK_Data_4, ///< A four-byte fixup. + FK_Data_8, ///< A eight-byte fixup. + FK_Data_6b, ///< A six-bits fixup. + FK_PCRel_1, ///< A one-byte pc relative fixup. + FK_PCRel_2, ///< A two-byte pc relative fixup. + FK_PCRel_4, ///< A four-byte pc relative fixup. + FK_PCRel_8, ///< A eight-byte pc relative fixup. + FK_GPRel_1, ///< A one-byte gp relative fixup. + FK_GPRel_2, ///< A two-byte gp relative fixup. + FK_GPRel_4, ///< A four-byte gp relative fixup. + FK_GPRel_8, ///< A eight-byte gp relative fixup. + FK_DTPRel_4, ///< A four-byte dtp relative fixup. + FK_DTPRel_8, ///< A eight-byte dtp relative fixup. + FK_TPRel_4, ///< A four-byte tp relative fixup. + FK_TPRel_8, ///< A eight-byte tp relative fixup. + FK_SecRel_1, ///< A one-byte section relative fixup. + FK_SecRel_2, ///< A two-byte section relative fixup. + FK_SecRel_4, ///< A four-byte section relative fixup. + FK_SecRel_8, ///< A eight-byte section relative fixup. + FK_Data_Add_1, ///< A one-byte add fixup. + FK_Data_Add_2, ///< A two-byte add fixup. + FK_Data_Add_4, ///< A four-byte add fixup. + FK_Data_Add_8, ///< A eight-byte add fixup. + FK_Data_Add_6b, ///< A six-bits add fixup. + FK_Data_Sub_1, ///< A one-byte sub fixup. + FK_Data_Sub_2, ///< A two-byte sub fixup. + FK_Data_Sub_4, ///< A four-byte sub fixup. + FK_Data_Sub_8, ///< A eight-byte sub fixup. + FK_Data_Sub_6b, ///< A six-bits sub fixup. FirstTargetFixupKind = 128, @@ -75,25 +78,25 @@ class MCFixup { /// The value to put into the fixup location. The exact interpretation of the /// expression is target dependent, usually it will be one of the operands to /// an instruction or an assembler directive. - const MCExpr *Value; + const MCExpr *Value = nullptr; /// The byte index of start of the relocation inside the MCFragment. - uint32_t Offset; + uint32_t Offset = 0; /// The target dependent kind of fixup item this is. The kind is used to /// determine how the operand value should be encoded into the instruction. - unsigned Kind; + MCFixupKind Kind = FK_NONE; /// The source location which gave rise to the fixup, if any. SMLoc Loc; public: static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc = SMLoc()) { - assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!"); + assert(Kind < MaxTargetFixupKind && "Kind out of range!"); MCFixup FI; FI.Value = Value; FI.Offset = Offset; - FI.Kind = unsigned(Kind); + FI.Kind = Kind; FI.Loc = Loc; return FI; } @@ -104,7 +107,7 @@ public: MCFixup FI; FI.Value = Fixup.getValue(); FI.Offset = Fixup.getOffset(); - FI.Kind = (unsigned)getAddKindForKind(Fixup.getKind()); + FI.Kind = getAddKindForKind(Fixup.getKind()); FI.Loc = Fixup.getLoc(); return FI; } @@ -115,12 +118,14 @@ public: MCFixup FI; FI.Value = Fixup.getValue(); FI.Offset = Fixup.getOffset(); - FI.Kind = (unsigned)getSubKindForKind(Fixup.getKind()); + FI.Kind = getSubKindForKind(Fixup.getKind()); FI.Loc = Fixup.getLoc(); return FI; } - MCFixupKind getKind() const { return MCFixupKind(Kind); } + MCFixupKind getKind() const { return Kind; } + + unsigned getTargetKind() const { return Kind; } uint32_t getOffset() const { return Offset; } void setOffset(uint32_t Value) { Offset = Value; } @@ -129,37 +134,63 @@ public: /// 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) { + static MCFixupKind getKindForSize(unsigned Size, bool IsPCRel) { switch (Size) { default: llvm_unreachable("Invalid generic fixup size!"); - case 1: return isPCRel ? FK_PCRel_1 : FK_Data_1; - case 2: return isPCRel ? FK_PCRel_2 : FK_Data_2; - case 4: return isPCRel ? FK_PCRel_4 : FK_Data_4; - case 8: return isPCRel ? FK_PCRel_8 : FK_Data_8; + case 1: + return IsPCRel ? FK_PCRel_1 : FK_Data_1; + case 2: + return IsPCRel ? FK_PCRel_2 : FK_Data_2; + case 4: + return IsPCRel ? FK_PCRel_4 : FK_Data_4; + case 8: + return IsPCRel ? FK_PCRel_8 : FK_Data_8; + } + } + + /// Return the generic fixup kind for a value with the given size in bits. + /// It is an error to pass an unsupported size. + static MCFixupKind getKindForSizeInBits(unsigned Size, bool IsPCRel) { + switch (Size) { + default: + llvm_unreachable("Invalid generic fixup size!"); + case 6: + assert(!IsPCRel && "Invalid pc-relative fixup size!"); + return FK_Data_6b; + case 8: + return IsPCRel ? FK_PCRel_1 : FK_Data_1; + case 16: + return IsPCRel ? FK_PCRel_2 : FK_Data_2; + case 32: + return IsPCRel ? FK_PCRel_4 : FK_Data_4; + case 64: + return IsPCRel ? FK_PCRel_8 : FK_Data_8; } } /// Return the generic fixup kind for an addition with a given size. It /// is an error to pass an unsupported size. - static MCFixupKind getAddKindForKind(unsigned Kind) { + static MCFixupKind getAddKindForKind(MCFixupKind Kind) { switch (Kind) { default: llvm_unreachable("Unknown type to convert!"); case FK_Data_1: return FK_Data_Add_1; case FK_Data_2: return FK_Data_Add_2; case FK_Data_4: return FK_Data_Add_4; case FK_Data_8: return FK_Data_Add_8; + case FK_Data_6b: return FK_Data_Add_6b; } } /// Return the generic fixup kind for an subtraction with a given size. It /// is an error to pass an unsupported size. - static MCFixupKind getSubKindForKind(unsigned Kind) { + static MCFixupKind getSubKindForKind(MCFixupKind Kind) { switch (Kind) { default: llvm_unreachable("Unknown type to convert!"); case FK_Data_1: return FK_Data_Sub_1; case FK_Data_2: return FK_Data_Sub_2; case FK_Data_4: return FK_Data_Sub_4; case FK_Data_8: return FK_Data_Sub_8; + case FK_Data_6b: return FK_Data_Sub_6b; } } diff --git a/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h index aadf2ce725ea..b0def566c46a 100644 --- a/include/llvm/MC/MCFragment.h +++ b/include/llvm/MC/MCFragment.h @@ -149,6 +149,7 @@ public: case MCFragment::FT_CompactEncodedInst: case MCFragment::FT_Data: case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: return true; } } @@ -232,7 +233,8 @@ public: static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data || - Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf;; + Kind == MCFragment::FT_CVDefRange || Kind == MCFragment::FT_Dwarf || + Kind == MCFragment::FT_DwarfFrame; } }; @@ -543,27 +545,21 @@ public: } }; -class MCDwarfCallFrameFragment : public MCFragment { +class MCDwarfCallFrameFragment : public MCEncodedFragmentWithFixups<8, 1> { /// AddrDelta - The expression for the difference of the two symbols that /// make up the address delta between two .cfi_* dwarf directives. const MCExpr *AddrDelta; - SmallString<8> Contents; - public: MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) - : MCFragment(FT_DwarfFrame, false, Sec), AddrDelta(&AddrDelta) { - Contents.push_back(0); - } + : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec), + AddrDelta(&AddrDelta) {} /// \name Accessors /// @{ const MCExpr &getAddrDelta() const { return *AddrDelta; } - SmallString<8> &getContents() { return Contents; } - const SmallString<8> &getContents() const { return Contents; } - /// @} static bool classof(const MCFragment *F) { diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 6bbc4bc2903b..4501ce3084c8 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -87,12 +87,10 @@ public: /// Utility functions to make adding mark ups simpler. StringRef markup(StringRef s) const; - StringRef markup(StringRef a, StringRef b) const; bool getPrintImmHex() const { return PrintImmHex; } void setPrintImmHex(bool Value) { PrintImmHex = Value; } - HexStyle::Style getPrintHexStyle() const { return PrintHexStyle; } void setPrintHexStyle(HexStyle::Style Value) { PrintHexStyle = Value; } /// Utility function to print immediates in decimal or hex. diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index dfefd7e72777..898ca47b13b8 100644 --- a/include/llvm/MC/MCInstrAnalysis.h +++ b/include/llvm/MC/MCInstrAnalysis.h @@ -152,6 +152,12 @@ public: evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, uint64_t &Target) const; + /// Given an instruction tries to get the address of a memory operand. Returns + /// the address on success. + virtual Optional<uint64_t> evaluateMemoryOperandAddress(const MCInst &Inst, + uint64_t Addr, + uint64_t Size) const; + /// Returns (PLT virtual address, GOT virtual address) pairs for PLT entries. virtual std::vector<std::pair<uint64_t, uint64_t>> findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents, diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 0aa586dfc901..e75a27614a22 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -56,7 +56,11 @@ enum OperandType { OPERAND_GENERIC_5 = 11, OPERAND_LAST_GENERIC = 11, - OPERAND_FIRST_TARGET = 12, + OPERAND_FIRST_GENERIC_IMM = 12, + OPERAND_GENERIC_IMM_0 = 12, + OPERAND_LAST_GENERIC_IMM = 12, + + OPERAND_FIRST_TARGET = 13, }; } @@ -103,6 +107,16 @@ public: assert(isGenericType() && "non-generic types don't have an index"); return OperandType - MCOI::OPERAND_FIRST_GENERIC; } + + bool isGenericImm() const { + return OperandType >= MCOI::OPERAND_FIRST_GENERIC_IMM && + OperandType <= MCOI::OPERAND_LAST_GENERIC_IMM; + } + + unsigned getGenericImmIndex() const { + assert(isGenericImm() && "non-generic immediates don't have an index"); + return OperandType - MCOI::OPERAND_FIRST_GENERIC_IMM; + } }; //===----------------------------------------------------------------------===// @@ -115,7 +129,8 @@ namespace MCID { /// not use these directly. These all correspond to bitfields in the /// MCInstrDesc::Flags field. enum Flag { - Variadic = 0, + PreISelOpcode = 0, + Variadic, HasOptionalDef, Pseudo, Return, @@ -228,6 +243,10 @@ public: /// Return flags of this instruction. uint64_t getFlags() const { return Flags; } + /// \returns true if this instruction is emitted before instruction selection + /// and should be legalized/regbankselected/selected. + bool isPreISelOpcode() const { return Flags & (1ULL << MCID::PreISelOpcode); } + /// Return true if this instruction can have a variable number of /// operands. In this case, the variable operands will be after the normal /// operands but before the implicit definitions and uses (if any are diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index f2a1364ad884..003491f32f75 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -61,6 +61,7 @@ static inline int MCLOHNameToId(StringRef Name) { MCLOHCaseNameToId(AdrpAdd) MCLOHCaseNameToId(AdrpLdrGot) .Default(-1); +#undef MCLOHCaseNameToId } static inline StringRef MCLOHIdToName(MCLOHType Kind) { @@ -76,6 +77,7 @@ static inline StringRef MCLOHIdToName(MCLOHType Kind) { MCLOHCaseIdToName(AdrpLdrGot); } return StringRef(); +#undef MCLOHCaseIdToName } static inline int MCLOHIdToNbArgs(MCLOHType Kind) { diff --git a/include/llvm/MC/MCRegister.h b/include/llvm/MC/MCRegister.h new file mode 100644 index 000000000000..8372947a4ba1 --- /dev/null +++ b/include/llvm/MC/MCRegister.h @@ -0,0 +1,110 @@ +//===-- llvm/MC/Register.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_REGISTER_H +#define LLVM_MC_REGISTER_H + +#include "llvm/ADT/DenseMapInfo.h" +#include <cassert> + +namespace llvm { + +/// An unsigned integer type large enough to represent all physical registers, +/// but not necessarily virtual registers. +using MCPhysReg = uint16_t; + +/// Wrapper class representing physical registers. Should be passed by value. +class MCRegister { + unsigned Reg; + +public: + MCRegister(unsigned Val = 0): Reg(Val) {} + + // Register numbers can represent physical registers, virtual registers, and + // sometimes stack slots. The unsigned values are divided into these ranges: + // + // 0 Not a register, can be used as a sentinel. + // [1;2^30) Physical registers assigned by TableGen. + // [2^30;2^31) Stack slots. (Rarely used.) + // [2^31;2^32) Virtual registers assigned by MachineRegisterInfo. + // + // Further sentinels can be allocated from the small negative integers. + // DenseMapInfo<unsigned> uses -1u and -2u. + + /// This is the portion of the positive number space that is not a physical + /// register. StackSlot values do not exist in the MC layer, see + /// Register::isStackSlot() for the more information on them. + /// + /// Note that isVirtualRegister() and isPhysicalRegister() cannot handle stack + /// slots, so if a variable may contains a stack slot, always check + /// isStackSlot() first. + static bool isStackSlot(unsigned Reg) { + return int(Reg) >= (1 << 30); + } + + /// Return true if the specified register number is in + /// the physical register namespace. + static bool isPhysicalRegister(unsigned Reg) { + assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first."); + return int(Reg) > 0; + } + + /// Return true if the specified register number is in the physical register + /// namespace. + bool isPhysical() const { + return isPhysicalRegister(Reg); + } + + operator unsigned() const { + return Reg; + } + + unsigned id() const { + return Reg; + } + + bool isValid() const { + return Reg != 0; + } + + /// Comparisons between register objects + bool operator==(const MCRegister &Other) const { return Reg == Other.Reg; } + bool operator!=(const MCRegister &Other) const { return Reg != Other.Reg; } + + /// Comparisons against register constants. E.g. + /// * R == AArch64::WZR + /// * R == 0 + /// * R == VirtRegMap::NO_PHYS_REG + bool operator==(unsigned Other) const { return Reg == Other; } + bool operator!=(unsigned Other) const { return Reg != Other; } + bool operator==(int Other) const { return Reg == unsigned(Other); } + bool operator!=(int Other) const { return Reg != unsigned(Other); } + // MSVC requires that we explicitly declare these two as well. + bool operator==(MCPhysReg Other) const { return Reg == unsigned(Other); } + bool operator!=(MCPhysReg Other) const { return Reg != unsigned(Other); } +}; + +// Provide DenseMapInfo for MCRegister +template<> struct DenseMapInfo<MCRegister> { + static inline unsigned getEmptyKey() { + return DenseMapInfo<unsigned>::getEmptyKey(); + } + static inline unsigned getTombstoneKey() { + return DenseMapInfo<unsigned>::getTombstoneKey(); + } + static unsigned getHashValue(const MCRegister &Val) { + return DenseMapInfo<unsigned>::getHashValue(Val.id()); + } + static bool isEqual(const MCRegister &LHS, const MCRegister &RHS) { + return DenseMapInfo<unsigned>::isEqual(LHS.id(), RHS.id()); + } +}; + +} + +#endif // ifndef LLVM_MC_REGISTER_H diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 92d39c3fcfb7..c7dc56ea588e 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -18,16 +18,13 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/iterator_range.h" #include "llvm/MC/LaneBitmask.h" +#include "llvm/MC/MCRegister.h" #include <cassert> #include <cstdint> #include <utility> namespace llvm { -/// An unsigned integer type large enough to represent all physical registers, -/// but not necessarily virtual registers. -using MCPhysReg = uint16_t; - /// MCRegisterClass - Base class of TargetRegisterClass. class MCRegisterClass { public: @@ -65,16 +62,17 @@ public: /// contains - Return true if the specified register is included in this /// register class. This does not include virtual registers. - bool contains(unsigned Reg) const { - unsigned InByte = Reg % 8; - unsigned Byte = Reg / 8; + bool contains(MCRegister Reg) const { + unsigned RegNo = unsigned(Reg); + unsigned InByte = RegNo % 8; + unsigned Byte = RegNo / 8; if (Byte >= RegSetSize) return false; return (RegSet[Byte] & (1 << InByte)) != 0; } /// contains - Return true if both registers are in this class. - bool contains(unsigned Reg1, unsigned Reg2) const { + bool contains(MCRegister Reg1, MCRegister Reg2) const { return contains(Reg1) && contains(Reg2); } @@ -148,8 +146,8 @@ public: private: const MCRegisterDesc *Desc; // Pointer to the descriptor array unsigned NumRegs; // Number of entries in the array - unsigned RAReg; // Return address register - unsigned PCReg; // Program counter register + MCRegister RAReg; // Return address register + MCRegister PCReg; // Program counter register const MCRegisterClass *Classes; // Pointer to the regclass array unsigned NumClasses; // Number of entries in the array unsigned NumRegUnits; // Number of regunits. @@ -175,8 +173,8 @@ private: const DwarfLLVMRegPair *EHL2DwarfRegs; // LLVM to Dwarf regs mapping EH const DwarfLLVMRegPair *Dwarf2LRegs; // Dwarf to LLVM regs mapping const DwarfLLVMRegPair *EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH - DenseMap<unsigned, int> L2SEHRegs; // LLVM to SEH regs mapping - DenseMap<unsigned, int> L2CVRegs; // LLVM to CV regs mapping + DenseMap<MCRegister, int> L2SEHRegs; // LLVM to SEH regs mapping + DenseMap<MCRegister, int> L2CVRegs; // LLVM to CV regs mapping public: /// DiffListIterator - Base iterator class that can traverse the @@ -202,7 +200,7 @@ public: /// advance - Move to the next list position, return the applied /// differential. This function does not detect the end of the list, that /// is the caller's responsibility (by checking for a 0 return value). - unsigned advance() { + MCRegister advance() { assert(isValid() && "Cannot move off the end of the list."); MCPhysReg D = *List++; Val += D; @@ -214,7 +212,7 @@ public: bool isValid() const { return List; } /// Dereference the iterator to get the value at the current position. - unsigned operator*() const { return Val; } + MCRegister operator*() const { return Val; } /// Pre-increment to move to the next position. void operator++() { @@ -309,26 +307,26 @@ public: /// as the LLVM register number. /// FIXME: TableGen these numbers. Currently this requires target specific /// initialization code. - void mapLLVMRegToSEHReg(unsigned LLVMReg, int SEHReg) { + void mapLLVMRegToSEHReg(MCRegister LLVMReg, int SEHReg) { L2SEHRegs[LLVMReg] = SEHReg; } - void mapLLVMRegToCVReg(unsigned LLVMReg, int CVReg) { + void mapLLVMRegToCVReg(MCRegister LLVMReg, int CVReg) { L2CVRegs[LLVMReg] = CVReg; } /// This method should return the register where the return /// address can be found. - unsigned getRARegister() const { + MCRegister getRARegister() const { return RAReg; } /// Return the register which is the program counter. - unsigned getProgramCounter() const { + MCRegister getProgramCounter() const { return PCReg; } - const MCRegisterDesc &operator[](unsigned RegNo) const { + const MCRegisterDesc &operator[](MCRegister RegNo) const { assert(RegNo < NumRegs && "Attempting to access record for invalid register number!"); return Desc[RegNo]; @@ -336,24 +334,24 @@ public: /// Provide a get method, equivalent to [], but more useful with a /// pointer to this object. - const MCRegisterDesc &get(unsigned RegNo) const { + const MCRegisterDesc &get(MCRegister RegNo) const { return operator[](RegNo); } /// Returns the physical register number of sub-register "Index" /// for physical register RegNo. Return zero if the sub-register does not /// exist. - unsigned getSubReg(unsigned Reg, unsigned Idx) const; + MCRegister getSubReg(MCRegister Reg, unsigned Idx) const; /// Return a super-register of the specified register /// Reg so its sub-register of index SubIdx is Reg. - unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, - const MCRegisterClass *RC) const; + MCRegister getMatchingSuperReg(MCRegister Reg, unsigned SubIdx, + const MCRegisterClass *RC) const; /// For a given register pair, return the sub-register index /// if the second register is a sub-register of the first. Return zero /// otherwise. - unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const; + unsigned getSubRegIndex(MCRegister RegNo, MCRegister SubRegNo) const; /// Get the size of the bit range covered by a sub-register index. /// If the index isn't continuous, return the sum of the sizes of its parts. @@ -367,7 +365,7 @@ public: /// Return the human-readable symbolic target-specific name for the /// specified physical register. - const char *getName(unsigned RegNo) const { + const char *getName(MCRegister RegNo) const { return RegStrings + get(RegNo).Name; } @@ -395,15 +393,11 @@ public: /// number. Returns -1 if there is no equivalent value. The second /// parameter allows targets to use different numberings for EH info and /// debugging info. - int getDwarfRegNum(unsigned RegNum, bool isEH) const; - - /// Map a dwarf register back to a target register. - int getLLVMRegNum(unsigned RegNum, bool isEH) const; + int getDwarfRegNum(MCRegister RegNum, bool isEH) const; - /// Map a DWARF EH register back to a target register (same as - /// getLLVMRegNum(RegNum, true)) but return -1 if there is no mapping, - /// rather than asserting that there must be one. - int getLLVMRegNumFromEH(unsigned RegNum) const; + /// Map a dwarf register back to a target register. Returns None is there is + /// no mapping. + Optional<unsigned> getLLVMRegNum(unsigned RegNum, bool isEH) const; /// Map a target EH register number to an equivalent DWARF register /// number. @@ -411,11 +405,11 @@ public: /// Map a target register to an equivalent SEH register /// number. Returns LLVM register number if there is no equivalent value. - int getSEHRegNum(unsigned RegNum) const; + int getSEHRegNum(MCRegister RegNum) const; /// Map a target register to an equivalent CodeView register /// number. - int getCodeViewRegNum(unsigned RegNum) const; + int getCodeViewRegNum(MCRegister RegNum) const; regclass_iterator regclass_begin() const { return Classes; } regclass_iterator regclass_end() const { return Classes+NumClasses; } @@ -439,34 +433,34 @@ public: } /// Returns the encoding for RegNo - uint16_t getEncodingValue(unsigned RegNo) const { + uint16_t getEncodingValue(MCRegister RegNo) const { assert(RegNo < NumRegs && "Attempting to get encoding for invalid register number!"); return RegEncodingTable[RegNo]; } /// Returns true if RegB is a sub-register of RegA. - bool isSubRegister(unsigned RegA, unsigned RegB) const { + bool isSubRegister(MCRegister RegA, MCRegister RegB) const { return isSuperRegister(RegB, RegA); } /// Returns true if RegB is a super-register of RegA. - bool isSuperRegister(unsigned RegA, unsigned RegB) const; + bool isSuperRegister(MCRegister RegA, MCRegister RegB) const; /// Returns true if RegB is a sub-register of RegA or if RegB == RegA. - bool isSubRegisterEq(unsigned RegA, unsigned RegB) const { + bool isSubRegisterEq(MCRegister RegA, MCRegister RegB) const { return isSuperRegisterEq(RegB, RegA); } /// Returns true if RegB is a super-register of RegA or if /// RegB == RegA. - bool isSuperRegisterEq(unsigned RegA, unsigned RegB) const { + bool isSuperRegisterEq(MCRegister RegA, MCRegister RegB) const { return RegA == RegB || isSuperRegister(RegA, RegB); } /// Returns true if RegB is a super-register or sub-register of RegA /// or if RegB == RegA. - bool isSuperOrSubRegisterEq(unsigned RegA, unsigned RegB) const { + bool isSuperOrSubRegisterEq(MCRegister RegA, MCRegister RegB) const { return isSubRegisterEq(RegA, RegB) || isSuperRegister(RegA, RegB); } }; @@ -482,8 +476,8 @@ public: /// If IncludeSelf is set, Reg itself is included in the list. class MCSubRegIterator : public MCRegisterInfo::DiffListIterator { public: - MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, - bool IncludeSelf = false) { + MCSubRegIterator(MCRegister Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { init(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs); // Initially, the iterator points to Reg itself. if (!IncludeSelf) @@ -500,13 +494,13 @@ class MCSubRegIndexIterator { public: /// Constructs an iterator that traverses subregisters and their /// associated subregister indices. - MCSubRegIndexIterator(unsigned Reg, const MCRegisterInfo *MCRI) + MCSubRegIndexIterator(MCRegister Reg, const MCRegisterInfo *MCRI) : SRIter(Reg, MCRI) { SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices; } /// Returns current sub-register. - unsigned getSubReg() const { + MCRegister getSubReg() const { return *SRIter; } @@ -531,7 +525,7 @@ class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { public: MCSuperRegIterator() = default; - MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + MCSuperRegIterator(MCRegister Reg, const MCRegisterInfo *MCRI, bool IncludeSelf = false) { init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs); // Initially, the iterator points to Reg itself. @@ -542,7 +536,7 @@ public: // Definition for isSuperRegister. Put it down here since it needs the // iterator defined above in addition to the MCRegisterInfo class itself. -inline bool MCRegisterInfo::isSuperRegister(unsigned RegA, unsigned RegB) const{ +inline bool MCRegisterInfo::isSuperRegister(MCRegister RegA, MCRegister RegB) const{ for (MCSuperRegIterator I(RegA, this); I.isValid(); ++I) if (*I == RegB) return true; @@ -569,7 +563,7 @@ public: /// in Reg. MCRegUnitIterator() = default; - MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + MCRegUnitIterator(MCRegister Reg, const MCRegisterInfo *MCRI) { assert(Reg && "Null register has no regunits"); // Decode the RegUnits MCRegisterDesc field. unsigned RU = MCRI->get(Reg).RegUnits; @@ -600,7 +594,7 @@ public: /// Constructs an iterator that traverses the register units and their /// associated LaneMasks in Reg. - MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI) + MCRegUnitMaskIterator(MCRegister Reg, const MCRegisterInfo *MCRI) : RUIter(Reg, MCRI) { uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks; MaskListIter = &MCRI->RegUnitMaskSequences[Idx]; @@ -667,7 +661,7 @@ public: /// any ordering or that entries are unique. class MCRegAliasIterator { private: - unsigned Reg; + MCRegister Reg; const MCRegisterInfo *MCRI; bool IncludeSelf; @@ -676,7 +670,7 @@ private: MCSuperRegIterator SI; public: - MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, + MCRegAliasIterator(MCRegister Reg, const MCRegisterInfo *MCRI, bool IncludeSelf) : Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) { // Initialize the iterators. @@ -692,7 +686,7 @@ public: bool isValid() const { return RI.isValid(); } - unsigned operator*() const { + MCRegister operator*() const { assert(SI.isValid() && "Cannot dereference an invalid iterator."); return *SI; } diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index 6fad1ec2069c..d057feda87d8 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/MC/MCFragment.h" #include "llvm/MC/SectionKind.h" +#include "llvm/Support/Alignment.h" #include <cassert> #include <utility> @@ -58,7 +59,7 @@ private: MCSymbol *Begin; MCSymbol *End = nullptr; /// The alignment requirement of this section. - unsigned Alignment = 1; + Align Alignment; /// The section index in the assemblers section list. unsigned Ordinal = 0; /// The index of this section in the layout order. @@ -117,8 +118,8 @@ public: MCSymbol *getEndSymbol(MCContext &Ctx); bool hasEnded() const; - unsigned getAlignment() const { return Alignment; } - void setAlignment(unsigned Value) { Alignment = Value; } + unsigned getAlignment() const { return Alignment.value(); } + void setAlignment(Align Value) { Alignment = Value; } unsigned getOrdinal() const { return Ordinal; } void setOrdinal(unsigned Value) { Ordinal = Value; } diff --git a/include/llvm/MC/MCSectionXCOFF.h b/include/llvm/MC/MCSectionXCOFF.h index 2a3f391fd3e2..ee302ed5ecec 100644 --- a/include/llvm/MC/MCSectionXCOFF.h +++ b/include/llvm/MC/MCSectionXCOFF.h @@ -23,16 +23,30 @@ class MCSymbol; // This class represents an XCOFF `Control Section`, more commonly referred to // as a csect. A csect represents the smallest possible unit of data/code which -// will be relocated as a single block. +// will be relocated as a single block. A csect can either be: +// 1) Initialized: The Type will be XTY_SD, and the symbols inside the csect +// will have a label definition representing their offset within the csect. +// 2) Uninitialized: The Type will be XTY_CM, it will contain a single symbol, +// and may not contain label definitions. +// 3) An external reference providing a symbol table entry for a symbol +// contained in another XCOFF object file. External reference csects are not +// implemented yet. class MCSectionXCOFF final : public MCSection { friend class MCContext; StringRef Name; XCOFF::StorageMappingClass MappingClass; + XCOFF::SymbolType Type; + XCOFF::StorageClass StorageClass; MCSectionXCOFF(StringRef Section, XCOFF::StorageMappingClass SMC, - SectionKind K, MCSymbol *Begin) - : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC) {} + XCOFF::SymbolType ST, XCOFF::StorageClass SC, SectionKind K, + MCSymbol *Begin) + : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC), + Type(ST), StorageClass(SC) { + assert((ST == XCOFF::XTY_SD || ST == XCOFF::XTY_CM) && + "Invalid or unhandled type for csect."); + } public: ~MCSectionXCOFF(); @@ -43,6 +57,8 @@ public: StringRef getSectionName() const { return Name; } XCOFF::StorageMappingClass getMappingClass() const { return MappingClass; } + XCOFF::StorageClass getStorageClass() const { return StorageClass; } + XCOFF::SymbolType getCSectType() const { return Type; } void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, raw_ostream &OS, diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 731e7515448c..6b48580ae57c 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -46,6 +46,7 @@ struct MCDwarfFrameInfo; class MCExpr; class MCInst; class MCInstPrinter; +class MCRegister; class MCSection; class MCStreamer; class MCSymbolRefExpr; @@ -53,6 +54,13 @@ class MCSubtargetInfo; class raw_ostream; class Twine; +namespace codeview { +struct DefRangeRegisterRelHeader; +struct DefRangeSubfieldRegisterHeader; +struct DefRangeRegisterHeader; +struct DefRangeFramePointerRelHeader; +} + using MCSectionSubPair = std::pair<MCSection *, const MCExpr *>; /// Target specific streamer interface. This is used so that targets can @@ -536,6 +544,15 @@ public: /// \param Symbol - Symbol the image relative relocation should point to. virtual void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset); + /// Emits an lcomm directive with XCOFF csect information. + /// + /// \param Symbol - The symbol we are emiting. + /// \param Size - The size of the block of storage. + /// \param ByteAlignment - The alignment of the symbol in bytes. Must be a power + /// of 2. + virtual void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + /// Emit an ELF .size directive. /// /// This corresponds to an assembler statement such as: @@ -860,6 +877,22 @@ public: ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, StringRef FixedSizePortion); + virtual void EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + codeview::DefRangeRegisterRelHeader DRHdr); + + virtual void EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + codeview::DefRangeSubfieldRegisterHeader DRHdr); + + virtual void EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + codeview::DefRangeRegisterHeader DRHdr); + + virtual void EmitCVDefRangeDirective( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + codeview::DefRangeFramePointerRelHeader DRHdr); + /// This implements the CodeView '.cv_stringtable' assembler directive. virtual void EmitCVStringTableDirective() {} @@ -917,13 +950,13 @@ public: virtual void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc = SMLoc()); virtual void EmitWinCFIStartChained(SMLoc Loc = SMLoc()); virtual void EmitWinCFIEndChained(SMLoc Loc = SMLoc()); - virtual void EmitWinCFIPushReg(unsigned Register, SMLoc Loc = SMLoc()); - virtual void EmitWinCFISetFrame(unsigned Register, unsigned Offset, + virtual void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc = SMLoc()); + virtual void EmitWinCFISetFrame(MCRegister Register, unsigned Offset, SMLoc Loc = SMLoc()); virtual void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc = SMLoc()); - virtual void EmitWinCFISaveReg(unsigned Register, unsigned Offset, + virtual void EmitWinCFISaveReg(MCRegister Register, unsigned Offset, SMLoc Loc = SMLoc()); - virtual void EmitWinCFISaveXMM(unsigned Register, unsigned Offset, + virtual void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset, SMLoc Loc = SMLoc()); virtual void EmitWinCFIPushFrame(bool Code, SMLoc Loc = SMLoc()); virtual void EmitWinCFIEndProlog(SMLoc Loc = SMLoc()); diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 9490a6ecedad..09130c4641ef 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -221,6 +221,52 @@ public: auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU); return Found != ProcDesc.end() && StringRef(Found->Key) == CPU; } + + virtual unsigned getHwMode() const { return 0; } + + /// Return the cache size in bytes for the given level of cache. + /// Level is zero-based, so a value of zero means the first level of + /// cache. + /// + virtual Optional<unsigned> getCacheSize(unsigned Level) const; + + /// Return the cache associatvity for the given level of cache. + /// Level is zero-based, so a value of zero means the first level of + /// cache. + /// + virtual Optional<unsigned> getCacheAssociativity(unsigned Level) const; + + /// Return the target cache line size in bytes at a given level. + /// + virtual Optional<unsigned> getCacheLineSize(unsigned Level) const; + + /// Return the target cache line size in bytes. By default, return + /// the line size for the bottom-most level of cache. This provides + /// a more convenient interface for the common case where all cache + /// levels have the same line size. Return zero if there is no + /// cache model. + /// + virtual unsigned getCacheLineSize() const { + Optional<unsigned> Size = getCacheLineSize(0); + if (Size) + return *Size; + + return 0; + } + + /// Return the preferred prefetch distance in terms of instructions. + /// + virtual unsigned getPrefetchDistance() const; + + /// Return the maximum prefetch distance in terms of loop + /// iterations. + /// + virtual unsigned getMaxPrefetchIterationsAhead() const; + + /// Return the minimum stride necessary to trigger software + /// prefetching. + /// + virtual unsigned getMinPrefetchStride() const; }; } // end namespace llvm diff --git a/include/llvm/MC/MCSymbolWasm.h b/include/llvm/MC/MCSymbolWasm.h index c50cd0ee4709..95beebe3f75a 100644 --- a/include/llvm/MC/MCSymbolWasm.h +++ b/include/llvm/MC/MCSymbolWasm.h @@ -54,6 +54,13 @@ public: modifyFlags(wasm::WASM_SYMBOL_EXPORTED, wasm::WASM_SYMBOL_EXPORTED); } + bool isNoStrip() const { + return getFlags() & wasm::WASM_SYMBOL_NO_STRIP; + } + void setNoStrip() const { + modifyFlags(wasm::WASM_SYMBOL_NO_STRIP, wasm::WASM_SYMBOL_NO_STRIP); + } + bool isWeak() const { return IsWeak; } void setWeak(bool isWeak) { IsWeak = isWeak; } diff --git a/include/llvm/MC/MCSymbolXCOFF.h b/include/llvm/MC/MCSymbolXCOFF.h index 0a1fe1475138..98ecd2466926 100644 --- a/include/llvm/MC/MCSymbolXCOFF.h +++ b/include/llvm/MC/MCSymbolXCOFF.h @@ -8,17 +8,49 @@ #ifndef LLVM_MC_MCSYMBOLXCOFF_H #define LLVM_MC_MCSYMBOLXCOFF_H +#include "llvm/ADT/Optional.h" #include "llvm/BinaryFormat/XCOFF.h" #include "llvm/MC/MCSymbol.h" namespace llvm { +class MCSectionXCOFF; + class MCSymbolXCOFF : public MCSymbol { public: MCSymbolXCOFF(const StringMapEntry<bool> *Name, bool isTemporary) : MCSymbol(SymbolKindXCOFF, Name, isTemporary) {} static bool classof(const MCSymbol *S) { return S->isXCOFF(); } + + void setStorageClass(XCOFF::StorageClass SC) { + assert((!StorageClass.hasValue() || StorageClass.getValue() == SC) && + "Redefining StorageClass of XCOFF MCSymbol."); + StorageClass = SC; + }; + + XCOFF::StorageClass getStorageClass() const { + assert(StorageClass.hasValue() && + "StorageClass not set on XCOFF MCSymbol."); + return StorageClass.getValue(); + } + + void setContainingCsect(MCSectionXCOFF *C) { + assert((!ContainingCsect || ContainingCsect == C) && + "Trying to set a containing csect that doesn't match the one that" + "this symbol is already mapped to."); + ContainingCsect = C; + } + + MCSectionXCOFF *getContainingCsect() const { + assert(ContainingCsect && + "Trying to get containing csect but none was set."); + return ContainingCsect; + } + +private: + Optional<XCOFF::StorageClass> StorageClass; + MCSectionXCOFF *ContainingCsect = nullptr; }; } // end namespace llvm diff --git a/include/llvm/MC/MCWasmObjectWriter.h b/include/llvm/MC/MCWasmObjectWriter.h index 4adbca28f116..fbb68549b503 100644 --- a/include/llvm/MC/MCWasmObjectWriter.h +++ b/include/llvm/MC/MCWasmObjectWriter.h @@ -20,9 +20,10 @@ class raw_pwrite_stream; class MCWasmObjectTargetWriter : public MCObjectTargetWriter { const unsigned Is64Bit : 1; + const unsigned IsEmscripten : 1; protected: - explicit MCWasmObjectTargetWriter(bool Is64Bit_); + explicit MCWasmObjectTargetWriter(bool Is64Bit_, bool IsEmscripten); public: virtual ~MCWasmObjectTargetWriter(); @@ -38,6 +39,7 @@ public: /// \name Accessors /// @{ bool is64Bit() const { return Is64Bit; } + bool isEmscripten() const { return IsEmscripten; } /// @} }; diff --git a/include/llvm/MC/MCXCOFFStreamer.h b/include/llvm/MC/MCXCOFFStreamer.h index 159ae4818749..b13b0031d18e 100644 --- a/include/llvm/MC/MCXCOFFStreamer.h +++ b/include/llvm/MC/MCXCOFFStreamer.h @@ -26,6 +26,8 @@ public: uint64_t Size = 0, unsigned ByteAlignment = 0, SMLoc Loc = SMLoc()) override; void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; + void EmitXCOFFLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlign) override; }; } // end namespace llvm diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h index c83eca4e512d..c8d4c3bbc262 100644 --- a/include/llvm/MC/StringTableBuilder.h +++ b/include/llvm/MC/StringTableBuilder.h @@ -22,7 +22,7 @@ class raw_ostream; /// Utility for building string tables with deduplicated suffixes. class StringTableBuilder { public: - enum Kind { ELF, WinCOFF, MachO, RAW, DWARF }; + enum Kind { ELF, WinCOFF, MachO, RAW, DWARF, XCOFF }; private: DenseMap<CachedHashStringRef, size_t> StringIndexMap; diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index fc9565ceafad..defbc3c64720 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -18,6 +18,7 @@ #define LLVM_MC_SUBTARGETFEATURE_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/MathExtras.h" #include <array> #include <bitset> #include <initializer_list> @@ -33,20 +34,123 @@ const unsigned MAX_SUBTARGET_WORDS = 3; const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64; /// Container class for subtarget features. -/// This is convenient because std::bitset does not have a constructor -/// with an initializer list of set bits. -class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> { -public: - // Cannot inherit constructors because it's not supported by VC++.. - FeatureBitset() = default; - - FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {} +/// This is a constexpr reimplementation of a subset of std::bitset. It would be +/// nice to use std::bitset directly, but it doesn't support constant +/// initialization. +class FeatureBitset { + static_assert((MAX_SUBTARGET_FEATURES % 64) == 0, + "Should be a multiple of 64!"); + // This cannot be a std::array, operator[] is not constexpr until C++17. + uint64_t Bits[MAX_SUBTARGET_WORDS] = {}; + +protected: + constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) { + for (unsigned I = 0; I != B.size(); ++I) + Bits[I] = B[I]; + } - FeatureBitset(std::initializer_list<unsigned> Init) { +public: + constexpr FeatureBitset() = default; + constexpr FeatureBitset(std::initializer_list<unsigned> Init) { for (auto I : Init) set(I); } + FeatureBitset &set() { + std::fill(std::begin(Bits), std::end(Bits), -1ULL); + return *this; + } + + constexpr FeatureBitset &set(unsigned I) { + // GCC <6.2 crashes if this is written in a single statement. + uint64_t NewBits = Bits[I / 64] | (uint64_t(1) << (I % 64)); + Bits[I / 64] = NewBits; + return *this; + } + + constexpr FeatureBitset &reset(unsigned I) { + // GCC <6.2 crashes if this is written in a single statement. + uint64_t NewBits = Bits[I / 64] & ~(uint64_t(1) << (I % 64)); + Bits[I / 64] = NewBits; + return *this; + } + + constexpr FeatureBitset &flip(unsigned I) { + // GCC <6.2 crashes if this is written in a single statement. + uint64_t NewBits = Bits[I / 64] ^ (uint64_t(1) << (I % 64)); + Bits[I / 64] = NewBits; + return *this; + } + + constexpr bool operator[](unsigned I) const { + uint64_t Mask = uint64_t(1) << (I % 64); + return (Bits[I / 64] & Mask) != 0; + } + + constexpr bool test(unsigned I) const { return (*this)[I]; } + + constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; } + + bool any() const { + return llvm::any_of(Bits, [](uint64_t I) { return I != 0; }); + } + bool none() const { return !any(); } + size_t count() const { + size_t Count = 0; + for (auto B : Bits) + Count += countPopulation(B); + return Count; + } + + constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) { + for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) { + Bits[I] ^= RHS.Bits[I]; + } + return *this; + } + constexpr FeatureBitset operator^(const FeatureBitset &RHS) const { + FeatureBitset Result = *this; + Result ^= RHS; + return Result; + } + + constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) { + for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) { + Bits[I] &= RHS.Bits[I]; + } + return *this; + } + constexpr FeatureBitset operator&(const FeatureBitset &RHS) const { + FeatureBitset Result = *this; + Result &= RHS; + return Result; + } + + constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) { + for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) { + Bits[I] |= RHS.Bits[I]; + } + return *this; + } + constexpr FeatureBitset operator|(const FeatureBitset &RHS) const { + FeatureBitset Result = *this; + Result |= RHS; + return Result; + } + + constexpr FeatureBitset operator~() const { + FeatureBitset Result = *this; + for (auto &B : Result.Bits) + B = ~B; + return Result; + } + + bool operator==(const FeatureBitset &RHS) const { + return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits)); + } + + bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); } + bool operator < (const FeatureBitset &Other) const { for (unsigned I = 0, E = size(); I != E; ++I) { bool LHS = test(I), RHS = Other.test(I); @@ -58,23 +162,12 @@ public: }; /// Class used to store the subtarget bits in the tables created by tablegen. -/// The std::initializer_list constructor of FeatureBitset can't be done at -/// compile time and requires a static constructor to run at startup. -class FeatureBitArray { - std::array<uint64_t, MAX_SUBTARGET_WORDS> Bits; - +class FeatureBitArray : public FeatureBitset { public: constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) - : Bits(B) {} - - FeatureBitset getAsBitset() const { - FeatureBitset Result; - - for (unsigned i = 0, e = Bits.size(); i != e; ++i) - Result |= FeatureBitset(Bits[i]) << (64 * i); + : FeatureBitset(B) {} - return Result; - } + const FeatureBitset &getAsBitset() const { return *this; } }; //===----------------------------------------------------------------------===// |