diff options
author | Alon Zakai <azakai@google.com> | 2019-12-19 09:04:08 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-12-19 09:04:08 -0800 |
commit | 4d28d3f32e7f213e300b24bc61c3f0ac9d6e1ab6 (patch) | |
tree | 91bffc2d47b1fe4bba01e7ada77006ef340bd138 /third_party/llvm-project/include/llvm/MC | |
parent | 0048f5b004ddf50e750aa335d0be314a73852058 (diff) | |
download | binaryen-4d28d3f32e7f213e300b24bc61c3f0ac9d6e1ab6.tar.gz binaryen-4d28d3f32e7f213e300b24bc61c3f0ac9d6e1ab6.tar.bz2 binaryen-4d28d3f32e7f213e300b24bc61c3f0ac9d6e1ab6.zip |
DWARF parsing and writing support using LLVM (#2520)
This imports LLVM code for DWARF handling. That code has the
Apache 2 license like us. It's also the same code used to
emit DWARF in the common toolchain, so it seems like a safe choice.
This adds two passes: --dwarfdump which runs the same code LLVM
runs for llvm-dwarfdump. This shows we can parse it ok, and will
be useful for debugging. And --dwarfupdate writes out the DWARF
sections (unchanged from what we read, so it just roundtrips - for
updating we need #2515).
This puts LLVM in thirdparty which is added here.
All the LLVM code is behind USE_LLVM_DWARF, which is on
by default, but off in JS for now, as it increases code size by 20%.
This current approach imports the LLVM files directly. This is not
how they are intended to be used, so it required a bunch of
local changes - more than I expected actually, for the platform-specific
stuff. For now this seems to work, so it may be good enough, but
in the long term we may want to switch to linking against libllvm.
A downside to doing that is that binaryen users would need to
have an LLVM build, and even in the waterfall builds we'd have a
problem - while we ship LLVM there anyhow, we constantly update
it, which means that binaryen would need to be on latest llvm all
the time too (which otherwise, given DWARF is quite stable, we
might not need to constantly update).
An even larger issue is that as I did this work I learned about how
DWARF works in LLVM, and while the reading code is easy to
reuse, the writing code is trickier. The main code path is heavily
integrated with the MC layer, which we don't have - we might want
to create a "fake MC layer" for that, but it sounds hard. Instead,
there is the YAML path which is used mostly for testing, and which
can convert DWARF to and from YAML and from binary. Using
the non-YAML parts there, we can convert binary DWARF to
the YAML layer's nice Info data, then convert that to binary. This
works, however, this is not the path LLVM uses normally, and it
supports only some basic DWARF sections - I had to add ranges
support, in fact. So if we need more complex things, we may end
up needing to use the MC layer approach, or consider some other
DWARF library. However, hopefully that should not affect the core
binaryen code which just calls a library for DWARF stuff.
Helps #2400
Diffstat (limited to 'third_party/llvm-project/include/llvm/MC')
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/LaneBitmask.h | 101 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/MCExpr.h | 616 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/MCFixup.h | 202 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/MCFragment.h | 663 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/MCInst.h | 225 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/MCRegister.h | 110 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/MCRegisterInfo.h | 721 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/MCSymbol.h | 441 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/MCSymbolWasm.h | 110 | ||||
-rw-r--r-- | third_party/llvm-project/include/llvm/MC/SubtargetFeature.h | 236 |
10 files changed, 3425 insertions, 0 deletions
diff --git a/third_party/llvm-project/include/llvm/MC/LaneBitmask.h b/third_party/llvm-project/include/llvm/MC/LaneBitmask.h new file mode 100644 index 000000000..d5f69287a --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/LaneBitmask.h @@ -0,0 +1,101 @@ +//===- llvm/MC/LaneBitmask.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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// A common definition of LaneBitmask for use in TableGen and CodeGen. +/// +/// A lane mask is a bitmask representing the covering of a register with +/// sub-registers. +/// +/// This is typically used to track liveness at sub-register granularity. +/// Lane masks for sub-register indices are similar to register units for +/// physical registers. The individual bits in a lane mask can't be assigned +/// any specific meaning. They can be used to check if two sub-register +/// indices overlap. +/// +/// Iff the target has a register such that: +/// +/// getSubReg(Reg, A) overlaps getSubReg(Reg, B) +/// +/// then: +/// +/// (getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B)) != 0 + +#ifndef LLVM_MC_LANEBITMASK_H +#define LLVM_MC_LANEBITMASK_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Printable.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + + struct LaneBitmask { + // When changing the underlying type, change the format string as well. + using Type = unsigned; + enum : unsigned { BitWidth = 8*sizeof(Type) }; + constexpr static const char *const FormatStr = "%08X"; + + constexpr LaneBitmask() = default; + explicit constexpr LaneBitmask(Type V) : Mask(V) {} + + constexpr bool operator== (LaneBitmask M) const { return Mask == M.Mask; } + constexpr bool operator!= (LaneBitmask M) const { return Mask != M.Mask; } + constexpr bool operator< (LaneBitmask M) const { return Mask < M.Mask; } + constexpr bool none() const { return Mask == 0; } + constexpr bool any() const { return Mask != 0; } + constexpr bool all() const { return ~Mask == 0; } + + constexpr LaneBitmask operator~() const { + return LaneBitmask(~Mask); + } + constexpr LaneBitmask operator|(LaneBitmask M) const { + return LaneBitmask(Mask | M.Mask); + } + constexpr LaneBitmask operator&(LaneBitmask M) const { + return LaneBitmask(Mask & M.Mask); + } + LaneBitmask &operator|=(LaneBitmask M) { + Mask |= M.Mask; + return *this; + } + LaneBitmask &operator&=(LaneBitmask M) { + Mask &= M.Mask; + return *this; + } + + constexpr Type getAsInteger() const { return Mask; } + + unsigned getNumLanes() const { + return countPopulation(Mask); + } + unsigned getHighestLane() const { + return Log2_32(Mask); + } + + static constexpr LaneBitmask getNone() { return LaneBitmask(0); } + static constexpr LaneBitmask getAll() { return ~LaneBitmask(0); } + static constexpr LaneBitmask getLane(unsigned Lane) { + return LaneBitmask(Type(1) << Lane); + } + + private: + Type Mask = 0; + }; + + /// Create Printable object to print LaneBitmasks on a \ref raw_ostream. + inline Printable PrintLaneMask(LaneBitmask LaneMask) { + return Printable([LaneMask](raw_ostream &OS) { + OS << format(LaneBitmask::FormatStr, LaneMask.getAsInteger()); + }); + } + +} // end namespace llvm + +#endif // LLVM_MC_LANEBITMASK_H diff --git a/third_party/llvm-project/include/llvm/MC/MCExpr.h b/third_party/llvm-project/include/llvm/MC/MCExpr.h new file mode 100644 index 000000000..eb2786501 --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/MCExpr.h @@ -0,0 +1,616 @@ +//===- MCExpr.h - Assembly Level Expressions --------------------*- 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_MCEXPR_H +#define LLVM_MC_MCEXPR_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/SMLoc.h" +#include <cstdint> + +namespace llvm { + +class MCAsmInfo; +class MCAsmLayout; +class MCAssembler; +class MCContext; +class MCFixup; +class MCFragment; +class MCSection; +class MCStreamer; +class MCSymbol; +class MCValue; +class raw_ostream; +class StringRef; + +using SectionAddrMap = DenseMap<const MCSection *, uint64_t>; + +/// Base class for the full range of assembler expressions which are +/// needed for parsing. +class MCExpr { +public: + enum ExprKind { + Binary, ///< Binary expressions. + Constant, ///< Constant expressions. + SymbolRef, ///< References to labels and assigned expressions. + Unary, ///< Unary expressions. + Target ///< Target specific expression. + }; + +private: + ExprKind Kind; + SMLoc Loc; + + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet) const; + +protected: + explicit MCExpr(ExprKind Kind, SMLoc Loc) : Kind(Kind), Loc(Loc) {} + + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const MCFixup *Fixup, + const SectionAddrMap *Addrs, bool InSet) const; + +public: + MCExpr(const MCExpr &) = delete; + MCExpr &operator=(const MCExpr &) = delete; + + /// \name Accessors + /// @{ + + ExprKind getKind() const { return Kind; } + SMLoc getLoc() const { return Loc; } + + /// @} + /// \name Utility Methods + /// @{ + + void print(raw_ostream &OS, const MCAsmInfo *MAI, + bool InParens = false) const; + void dump() const; + + /// @} + /// \name Expression Evaluation + /// @{ + + /// 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 + /// values. If not given, then only non-symbolic expressions will be + /// evaluated. + /// \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 MCAssembler *Asm) const; + bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + + bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + + /// 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. + /// \return - True on success. + bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const; + + /// Try to evaluate the expression to the form (a - b + constant) where + /// 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 .size directive. + bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const; + + /// 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. + MCFragment *findAssociatedFragment() const; + + /// @} +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { + E.print(OS, nullptr); + return OS; +} + +//// Represent a constant integer expression. +class MCConstantExpr : public MCExpr { + int64_t Value; + bool PrintInHex = false; + + explicit MCConstantExpr(int64_t Value) + : MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {} + + MCConstantExpr(int64_t Value, bool PrintInHex) + : MCExpr(MCExpr::Constant, SMLoc()), Value(Value), + PrintInHex(PrintInHex) {} + +public: + /// \name Construction + /// @{ + + static const MCConstantExpr *create(int64_t Value, MCContext &Ctx, + bool PrintInHex = false); + + /// @} + /// \name Accessors + /// @{ + + int64_t getValue() const { return Value; } + + bool useHexFormat() const { return PrintInHex; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Constant; + } +}; + +/// 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 : uint16_t { + VK_None, + VK_Invalid, + + VK_GOT, + VK_GOTOFF, + VK_GOTREL, + VK_GOTPCREL, + VK_GOTTPOFF, + VK_INDNTPOFF, + VK_NTPOFF, + VK_GOTNTPOFF, + VK_PLT, + VK_TLSGD, + VK_TLSLD, + VK_TLSLDM, + VK_TPOFF, + VK_DTPOFF, + VK_TLSCALL, // symbol(tlscall) + VK_TLSDESC, // symbol(tlsdesc) + VK_TLVP, // Mach-O thread local variable relocations + VK_TLVPPAGE, + VK_TLVPPAGEOFF, + VK_PAGE, + VK_PAGEOFF, + VK_GOTPAGE, + VK_GOTPAGEOFF, + VK_SECREL, + VK_SIZE, // symbol@SIZE + VK_WEAKREF, // The link between the symbols in .weakref foo, bar + + VK_X86_ABS8, + + VK_ARM_NONE, + VK_ARM_GOT_PREL, + VK_ARM_TARGET1, + VK_ARM_TARGET2, + VK_ARM_PREL31, + VK_ARM_SBREL, // symbol(sbrel) + VK_ARM_TLSLDO, // symbol(tlsldo) + VK_ARM_TLSDESCSEQ, + + VK_AVR_NONE, + VK_AVR_LO8, + VK_AVR_HI8, + VK_AVR_HLO8, + VK_AVR_DIFF8, + VK_AVR_DIFF16, + VK_AVR_DIFF32, + + VK_PPC_LO, // symbol@l + VK_PPC_HI, // symbol@h + VK_PPC_HA, // symbol@ha + VK_PPC_HIGH, // symbol@high + VK_PPC_HIGHA, // symbol@higha + VK_PPC_HIGHER, // symbol@higher + VK_PPC_HIGHERA, // symbol@highera + VK_PPC_HIGHEST, // symbol@highest + VK_PPC_HIGHESTA, // symbol@highesta + VK_PPC_GOT_LO, // symbol@got@l + VK_PPC_GOT_HI, // symbol@got@h + VK_PPC_GOT_HA, // symbol@got@ha + VK_PPC_TOCBASE, // symbol@tocbase + VK_PPC_TOC, // symbol@toc + 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 + VK_PPC_TPREL_HA, // symbol@tprel@ha + VK_PPC_TPREL_HIGH, // symbol@tprel@high + VK_PPC_TPREL_HIGHA, // symbol@tprel@higha + VK_PPC_TPREL_HIGHER, // symbol@tprel@higher + VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera + VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest + VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta + VK_PPC_DTPREL_LO, // symbol@dtprel@l + VK_PPC_DTPREL_HI, // symbol@dtprel@h + VK_PPC_DTPREL_HA, // symbol@dtprel@ha + VK_PPC_DTPREL_HIGH, // symbol@dtprel@high + VK_PPC_DTPREL_HIGHA, // symbol@dtprel@higha + VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher + VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera + VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest + VK_PPC_DTPREL_HIGHESTA,// symbol@dtprel@highesta + VK_PPC_GOT_TPREL, // symbol@got@tprel + VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l + VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h + VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha + VK_PPC_GOT_DTPREL, // symbol@got@dtprel + VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l + VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h + VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha + VK_PPC_TLS, // symbol@tls + VK_PPC_GOT_TLSGD, // symbol@got@tlsgd + VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h + VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha + VK_PPC_TLSGD, // symbol@tlsgd + VK_PPC_GOT_TLSLD, // symbol@got@tlsld + VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h + VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha + VK_PPC_TLSLD, // symbol@tlsld + VK_PPC_LOCAL, // symbol@local + + 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_WASM_TYPEINDEX, // Reference to a symbol's type (signature) + VK_WASM_MBREL, // Memory address relative to memory base + VK_WASM_TBREL, // Table index relative to table bare + + VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo + VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi + VK_AMDGPU_REL32_LO, // symbol@rel32@lo + VK_AMDGPU_REL32_HI, // symbol@rel32@hi + VK_AMDGPU_REL64, // symbol@rel64 + VK_AMDGPU_ABS32_LO, // symbol@abs32@lo + VK_AMDGPU_ABS32_HI, // symbol@abs32@hi + + VK_TPREL, + VK_DTPREL + }; + +private: + /// The symbol reference modifier. + const VariantKind Kind; + + /// Specifies how the variant kind should be printed. + const unsigned UseParensForSymbolVariant : 1; + + // FIXME: Remove this bit. + const unsigned HasSubsectionsViaSymbols : 1; + + /// The symbol being referenced. + const MCSymbol *Symbol; + + explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, + const MCAsmInfo *MAI, SMLoc Loc = SMLoc()); + +public: + /// \name Construction + /// @{ + + static const MCSymbolRefExpr *create(const MCSymbol *Symbol, MCContext &Ctx) { + return MCSymbolRefExpr::create(Symbol, VK_None, Ctx); + } + + static const MCSymbolRefExpr *create(const MCSymbol *Symbol, VariantKind Kind, + MCContext &Ctx, SMLoc Loc = SMLoc()); + static const MCSymbolRefExpr *create(StringRef Name, VariantKind Kind, + MCContext &Ctx); + + /// @} + /// \name Accessors + /// @{ + + const MCSymbol &getSymbol() const { return *Symbol; } + + VariantKind getKind() const { return Kind; } + + void printVariantKind(raw_ostream &OS) const; + + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } + + /// @} + /// \name Static Utility Functions + /// @{ + + static StringRef getVariantKindName(VariantKind Kind); + + static VariantKind getVariantKindForName(StringRef Name); + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::SymbolRef; + } +}; + +/// Unary assembler expressions. +class MCUnaryExpr : public MCExpr { +public: + enum Opcode { + LNot, ///< Logical negation. + Minus, ///< Unary minus. + Not, ///< Bitwise negation. + Plus ///< Unary plus. + }; + +private: + Opcode Op; + const MCExpr *Expr; + + MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc) + : MCExpr(MCExpr::Unary, Loc), Op(Op), Expr(Expr) {} + +public: + /// \name Construction + /// @{ + + static const MCUnaryExpr *create(Opcode Op, const MCExpr *Expr, + MCContext &Ctx, SMLoc Loc = SMLoc()); + + static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { + return create(LNot, Expr, Ctx, Loc); + } + + static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { + return create(Minus, Expr, Ctx, Loc); + } + + static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { + return create(Not, Expr, Ctx, Loc); + } + + static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { + return create(Plus, Expr, Ctx, Loc); + } + + /// @} + /// \name Accessors + /// @{ + + /// Get the kind of this unary expression. + Opcode getOpcode() const { return Op; } + + /// Get the child of this unary expression. + const MCExpr *getSubExpr() const { return Expr; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Unary; + } +}; + +/// Binary assembler expressions. +class MCBinaryExpr : public MCExpr { +public: + enum Opcode { + Add, ///< Addition. + And, ///< Bitwise and. + Div, ///< Signed division. + EQ, ///< Equality comparison. + GT, ///< Signed greater than comparison (result is either 0 or some + ///< target-specific non-zero value) + GTE, ///< Signed greater than or equal comparison (result is either 0 or + ///< some target-specific non-zero value). + LAnd, ///< Logical and. + LOr, ///< Logical or. + LT, ///< Signed less than comparison (result is either 0 or + ///< some target-specific non-zero value). + LTE, ///< Signed less than or equal comparison (result is either 0 or + ///< some target-specific non-zero value). + Mod, ///< Signed remainder. + Mul, ///< Multiplication. + NE, ///< Inequality comparison. + Or, ///< Bitwise or. + Shl, ///< Shift left. + AShr, ///< Arithmetic shift right. + LShr, ///< Logical shift right. + Sub, ///< Subtraction. + Xor ///< Bitwise exclusive or. + }; + +private: + Opcode Op; + const MCExpr *LHS, *RHS; + + MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, + SMLoc Loc = SMLoc()) + : MCExpr(MCExpr::Binary, Loc), Op(Op), LHS(LHS), RHS(RHS) {} + +public: + /// \name Construction + /// @{ + + static const MCBinaryExpr *create(Opcode Op, const MCExpr *LHS, + const MCExpr *RHS, MCContext &Ctx, + SMLoc Loc = SMLoc()); + + static const MCBinaryExpr *createAdd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Add, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createAnd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(And, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createDiv(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Div, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createEQ(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(EQ, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createGT(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(GT, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createGTE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(GTE, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLAnd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LAnd, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLOr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LOr, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLT(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LT, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createLTE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(LTE, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createMod(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Mod, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createMul(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Mul, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createNE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(NE, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createOr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Or, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createShl(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Shl, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createAShr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &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) { + return create(Sub, LHS, RHS, Ctx); + } + + static const MCBinaryExpr *createXor(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Xor, LHS, RHS, Ctx); + } + + /// @} + /// \name Accessors + /// @{ + + /// Get the kind of this binary expression. + Opcode getOpcode() const { return Op; } + + /// Get the left-hand side expression of the binary operator. + const MCExpr *getLHS() const { return LHS; } + + /// Get the right-hand side expression of the binary operator. + const MCExpr *getRHS() const { return RHS; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Binary; + } +}; + +/// 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. +class MCTargetExpr : public MCExpr { + virtual void anchor(); + +protected: + MCTargetExpr() : MCExpr(Target, SMLoc()) {} + virtual ~MCTargetExpr() = default; + +public: + virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0; + virtual bool evaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout, + const MCFixup *Fixup) const = 0; + // allow Target Expressions to be checked for equality + virtual bool isEqualTo(const MCExpr *x) const { return false; } + // This should be set when assigned expressions are not valid ".set" + // expressions, e.g. registers, and must be inlined. + virtual bool inlineAssignedExpr() const { return false; } + virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; + virtual MCFragment *findAssociatedFragment() const = 0; + + virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCEXPR_H diff --git a/third_party/llvm-project/include/llvm/MC/MCFixup.h b/third_party/llvm-project/include/llvm/MC/MCFixup.h new file mode 100644 index 000000000..29e321e23 --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/MCFixup.h @@ -0,0 +1,202 @@ +//===-- llvm/MC/MCFixup.h - Instruction Relocation and Patching -*- 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_MCFIXUP_H +#define LLVM_MC_MCFIXUP_H + +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SMLoc.h" +#include <cassert> + +namespace llvm { +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_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, + + // Limit range of target fixups, in case we want to pack more efficiently + // later. + MaxTargetFixupKind = (1 << 8) +}; + +/// Encode information on a single operation to perform on a byte +/// sequence (e.g., an encoded instruction) which requires assemble- or run- +/// time patching. +/// +/// Fixups are used any time the target instruction encoder needs to represent +/// some value in an instruction which is not yet concrete. The encoder will +/// encode the instruction assuming the value is 0, and emit a fixup which +/// communicates to the assembler backend how it should rewrite the encoded +/// value. +/// +/// During the process of relaxation, the assembler will apply fixups as +/// symbolic values become concrete. When relaxation is complete, any remaining +/// fixups become relocations in the object file (or errors, if the fixup cannot +/// be encoded on the target). +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 = nullptr; + + /// The byte index of start of the relocation inside the MCFragment. + 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. + 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(Kind < MaxTargetFixupKind && "Kind out of range!"); + MCFixup FI; + FI.Value = Value; + FI.Offset = Offset; + FI.Kind = Kind; + FI.Loc = Loc; + return FI; + } + + /// Return a fixup corresponding to the add half of a add/sub fixup pair for + /// the given Fixup. + static MCFixup createAddFor(const MCFixup &Fixup) { + MCFixup FI; + FI.Value = Fixup.getValue(); + FI.Offset = Fixup.getOffset(); + FI.Kind = getAddKindForKind(Fixup.getKind()); + FI.Loc = Fixup.getLoc(); + return FI; + } + + /// Return a fixup corresponding to the sub half of a add/sub fixup pair for + /// the given Fixup. + static MCFixup createSubFor(const MCFixup &Fixup) { + MCFixup FI; + FI.Value = Fixup.getValue(); + FI.Offset = Fixup.getOffset(); + FI.Kind = getSubKindForKind(Fixup.getKind()); + FI.Loc = Fixup.getLoc(); + return FI; + } + + MCFixupKind getKind() const { return Kind; } + + unsigned getTargetKind() const { return Kind; } + + uint32_t getOffset() const { return Offset; } + void setOffset(uint32_t Value) { Offset = Value; } + + const MCExpr *getValue() const { return Value; } + + /// 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!"); + 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(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(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; + } + } + + SMLoc getLoc() const { return Loc; } +}; + +} // End llvm namespace + +#endif diff --git a/third_party/llvm-project/include/llvm/MC/MCFragment.h b/third_party/llvm-project/include/llvm/MC/MCFragment.h new file mode 100644 index 000000000..b0def566c --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/MCFragment.h @@ -0,0 +1,663 @@ +//===- MCFragment.h - Fragment type hierarchy -------------------*- 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_MCFRAGMENT_H +#define LLVM_MC_MCFRAGMENT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/SMLoc.h" +#include <cstdint> +#include <utility> + +namespace llvm { + +class MCSection; +class MCSubtargetInfo; +class MCSymbol; + +class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> { + friend class MCAsmLayout; + +public: + enum FragmentType : uint8_t { + FT_Align, + FT_Data, + FT_CompactEncodedInst, + FT_Fill, + FT_Relaxable, + FT_Org, + FT_Dwarf, + FT_DwarfFrame, + FT_LEB, + FT_Padding, + FT_SymbolId, + FT_CVInlineLines, + FT_CVDefRange, + FT_Dummy + }; + +private: + FragmentType Kind; + +protected: + bool HasInstructions; + +private: + /// LayoutOrder - The layout order of this fragment. + unsigned LayoutOrder; + + /// The data for the section this fragment is in. + MCSection *Parent; + + /// Atom - The atom this fragment is in, as represented by its defining + /// symbol. + const MCSymbol *Atom; + + /// \name Assembler Backend Data + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + /// Offset - The offset of this fragment in its section. This is ~0 until + /// initialized. + uint64_t Offset; + + /// @} + +protected: + MCFragment(FragmentType Kind, bool HasInstructions, + MCSection *Parent = nullptr); + + ~MCFragment(); + +public: + MCFragment() = delete; + MCFragment(const MCFragment &) = delete; + MCFragment &operator=(const MCFragment &) = delete; + + /// Destroys the current fragment. + /// + /// This must be used instead of delete as MCFragment is non-virtual. + /// This method will dispatch to the appropriate subclass. + void destroy(); + + FragmentType getKind() const { return Kind; } + + MCSection *getParent() const { return Parent; } + void setParent(MCSection *Value) { Parent = 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; } + + /// Does this fragment have instructions emitted into it? By default + /// this is false, but specific fragment types may set it to true. + bool hasInstructions() const { return HasInstructions; } + + /// Return true if given frgment has FT_Dummy type. + bool isDummy() const { return Kind == FT_Dummy; } + + void dump() const; +}; + +class MCDummyFragment : public MCFragment { +public: + explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {} + + static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data. +/// +class MCEncodedFragment : public MCFragment { + /// Should this fragment be aligned to the end of a bundle? + bool AlignToBundleEnd = false; + + uint8_t BundlePadding = 0; + +protected: + MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions, + MCSection *Sec) + : MCFragment(FType, HasInstructions, Sec) {} + + /// STI - The MCSubtargetInfo in effect when the instruction was encoded. + /// must be non-null for instructions. + const MCSubtargetInfo *STI = nullptr; + +public: + 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: + case MCFragment::FT_Dwarf: + case MCFragment::FT_DwarfFrame: + return true; + } + } + + /// Should this fragment be placed at the end of an aligned bundle? + bool alignToBundleEnd() const { return AlignToBundleEnd; } + void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + + /// Get the padding size that must be inserted before this fragment. + /// Used for bundling. By default, no padding is inserted. + /// Note that padding size is restricted to 8 bits. This is an optimization + /// to reduce the amount of space used for each fragment. In practice, larger + /// padding should never be required. + uint8_t getBundlePadding() const { return BundlePadding; } + + /// Set the padding size for this fragment. By default it's a no-op, + /// and only some fragments have a meaningful implementation. + void setBundlePadding(uint8_t N) { BundlePadding = N; } + + /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. + /// Guaranteed to be non-null if hasInstructions() == true + const MCSubtargetInfo *getSubtargetInfo() const { return STI; } + + /// Record that the fragment contains instructions with the MCSubtargetInfo in + /// effect when the instruction was encoded. + void setHasInstructions(const MCSubtargetInfo &STI) { + HasInstructions = true; + this->STI = &STI; + } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data. +/// +template<unsigned ContentsSize> +class MCEncodedFragmentWithContents : public MCEncodedFragment { + SmallVector<char, ContentsSize> Contents; + +protected: + MCEncodedFragmentWithContents(MCFragment::FragmentType FType, + bool HasInstructions, + MCSection *Sec) + : MCEncodedFragment(FType, HasInstructions, Sec) {} + +public: + SmallVectorImpl<char> &getContents() { return Contents; } + const SmallVectorImpl<char> &getContents() const { return Contents; } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data and also have fixups registered. +/// +template<unsigned ContentsSize, unsigned FixupsSize> +class MCEncodedFragmentWithFixups : + public MCEncodedFragmentWithContents<ContentsSize> { + + /// Fixups - The list of fixups in this fragment. + SmallVector<MCFixup, FixupsSize> Fixups; + +protected: + MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, + bool HasInstructions, + MCSection *Sec) + : MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions, + Sec) {} + +public: + + using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator; + using fixup_iterator = SmallVectorImpl<MCFixup>::iterator; + + SmallVectorImpl<MCFixup> &getFixups() { return Fixups; } + const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; } + + fixup_iterator fixup_begin() { return Fixups.begin(); } + const_fixup_iterator fixup_begin() const { return Fixups.begin(); } + + fixup_iterator fixup_end() { return Fixups.end(); } + const_fixup_iterator fixup_end() const { return Fixups.end(); } + + 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_DwarfFrame; + } +}; + +/// Fragment for data and encoded instructions. +/// +class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { +public: + MCDataFragment(MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Data; + } +}; + +/// This is a compact (memory-size-wise) fragment for holding an encoded +/// instruction (non-relaxable) that has no fixups registered. When applicable, +/// it can be used instead of MCDataFragment and lead to lower memory +/// consumption. +/// +class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> { +public: + MCCompactEncodedInstFragment(MCSection *Sec = nullptr) + : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) { + } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_CompactEncodedInst; + } +}; + +/// A relaxable fragment holds on to its MCInst, since it may need to be +/// relaxed during the assembler layout and relaxation stage. +/// +class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> { + + /// Inst - The instruction this is a fragment for. + MCInst Inst; + +public: + MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, + MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec), + Inst(Inst) { this->STI = &STI; } + + const MCInst &getInst() const { return Inst; } + void setInst(const MCInst &Value) { Inst = Value; } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Relaxable; + } +}; + +class MCAlignFragment : public MCFragment { + /// Alignment - The alignment to ensure, in bytes. + unsigned Alignment; + + /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead + /// of using the provided value. The exact interpretation of this flag is + /// target dependent. + bool EmitNops : 1; + + /// Value - Value to use for filling padding bytes. + int64_t Value; + + /// ValueSize - The size of the integer (in bytes) of \p Value. + unsigned ValueSize; + + /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment + /// cannot be satisfied in this width then this fragment is ignored. + unsigned MaxBytesToEmit; + +public: + MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, + unsigned MaxBytesToEmit, MCSection *Sec = nullptr) + : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false), + Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} + + /// \name Accessors + /// @{ + + unsigned getAlignment() const { return Alignment; } + + int64_t getValue() const { return Value; } + + unsigned getValueSize() const { return ValueSize; } + + unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } + + bool hasEmitNops() const { return EmitNops; } + void setEmitNops(bool Value) { EmitNops = Value; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Align; + } +}; + +/// Fragment for adding required padding. +/// This fragment is always inserted before an instruction, and holds that +/// instruction as context information (as well as a mask of kinds) for +/// determining the padding size. +/// +class MCPaddingFragment : public MCFragment { + /// A mask containing all the kinds relevant to this fragment. i.e. the i'th + /// bit will be set iff kind i is relevant to this fragment. + uint64_t PaddingPoliciesMask; + /// A boolean indicating if this fragment will actually hold padding. If its + /// value is false, then this fragment serves only as a placeholder, + /// containing data to assist other insertion point in their decision making. + bool IsInsertionPoint; + + uint64_t Size; + + struct MCInstInfo { + bool IsInitialized; + MCInst Inst; + /// A boolean indicating whether the instruction pointed by this fragment is + /// a fixed size instruction or a relaxable instruction held by a + /// MCRelaxableFragment. + bool IsImmutableSizedInst; + union { + /// If the instruction is a fixed size instruction, hold its size. + size_t InstSize; + /// Otherwise, hold a pointer to the MCRelaxableFragment holding it. + MCRelaxableFragment *InstFragment; + }; + }; + MCInstInfo InstInfo; + +public: + static const uint64_t PFK_None = UINT64_C(0); + + enum MCPaddingFragmentKind { + // values 0-7 are reserved for future target independet values. + + FirstTargetPerfNopFragmentKind = 8, + + /// Limit range of target MCPerfNopFragment kinds to fit in uint64_t + MaxTargetPerfNopFragmentKind = 63 + }; + + MCPaddingFragment(MCSection *Sec = nullptr) + : MCFragment(FT_Padding, false, Sec), PaddingPoliciesMask(PFK_None), + IsInsertionPoint(false), Size(UINT64_C(0)), + InstInfo({false, MCInst(), false, {0}}) {} + + bool isInsertionPoint() const { return IsInsertionPoint; } + void setAsInsertionPoint() { IsInsertionPoint = true; } + uint64_t getPaddingPoliciesMask() const { return PaddingPoliciesMask; } + void setPaddingPoliciesMask(uint64_t Value) { PaddingPoliciesMask = Value; } + bool hasPaddingPolicy(uint64_t PolicyMask) const { + assert(isPowerOf2_64(PolicyMask) && + "Policy mask must contain exactly one policy"); + return (getPaddingPoliciesMask() & PolicyMask) != PFK_None; + } + const MCInst &getInst() const { + assert(isInstructionInitialized() && "Fragment has no instruction!"); + return InstInfo.Inst; + } + size_t getInstSize() const { + assert(isInstructionInitialized() && "Fragment has no instruction!"); + if (InstInfo.IsImmutableSizedInst) + return InstInfo.InstSize; + assert(InstInfo.InstFragment != nullptr && + "Must have a valid InstFragment to retrieve InstSize from"); + return InstInfo.InstFragment->getContents().size(); + } + void setInstAndInstSize(const MCInst &Inst, size_t InstSize) { + InstInfo.IsInitialized = true; + InstInfo.IsImmutableSizedInst = true; + InstInfo.Inst = Inst; + InstInfo.InstSize = InstSize; + } + void setInstAndInstFragment(const MCInst &Inst, + MCRelaxableFragment *InstFragment) { + InstInfo.IsInitialized = true; + InstInfo.IsImmutableSizedInst = false; + InstInfo.Inst = Inst; + InstInfo.InstFragment = InstFragment; + } + uint64_t getSize() const { return Size; } + void setSize(uint64_t Value) { Size = Value; } + bool isInstructionInitialized() const { return InstInfo.IsInitialized; } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Padding; + } +}; + +class MCFillFragment : public MCFragment { + /// Value to use for filling bytes. + uint64_t Value; + uint8_t ValueSize; + /// The number of bytes to insert. + const MCExpr &NumValues; + + /// Source location of the directive that this fragment was created for. + SMLoc Loc; + +public: + MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues, + SMLoc Loc, MCSection *Sec = nullptr) + : MCFragment(FT_Fill, false, Sec), Value(Value), ValueSize(VSize), + NumValues(NumValues), Loc(Loc) {} + + uint64_t getValue() const { return Value; } + uint8_t getValueSize() const { return ValueSize; } + const MCExpr &getNumValues() const { return NumValues; } + + SMLoc getLoc() const { return Loc; } + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Fill; + } +}; + +class MCOrgFragment : public MCFragment { + /// The offset this fragment should start at. + const MCExpr *Offset; + + /// Value to use for filling bytes. + int8_t Value; + + /// Source location of the directive that this fragment was created for. + SMLoc Loc; + +public: + MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc, + MCSection *Sec = nullptr) + : MCFragment(FT_Org, false, Sec), Offset(&Offset), Value(Value), Loc(Loc) {} + + /// \name Accessors + /// @{ + + const MCExpr &getOffset() const { return *Offset; } + + uint8_t getValue() const { return Value; } + + SMLoc getLoc() const { return Loc; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Org; + } +}; + +class MCLEBFragment : public MCFragment { + /// Value - The value this fragment should contain. + const MCExpr *Value; + + /// IsSigned - True if this is a sleb128, false if uleb128. + bool IsSigned; + + SmallString<8> Contents; + +public: + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) + : MCFragment(FT_LEB, false, Sec), Value(&Value_), IsSigned(IsSigned_) { + Contents.push_back(0); + } + + /// \name Accessors + /// @{ + + const MCExpr &getValue() const { return *Value; } + + bool isSigned() const { return IsSigned; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_LEB; + } +}; + +class MCDwarfLineAddrFragment : public MCEncodedFragmentWithFixups<8, 1> { + /// LineDelta - the value of the difference between the two line numbers + /// between two .loc dwarf directives. + int64_t LineDelta; + + /// AddrDelta - The expression for the difference of the two symbols that + /// make up the address delta between two .loc dwarf directives. + const MCExpr *AddrDelta; + +public: + MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, + MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<8, 1>(FT_Dwarf, false, Sec), + LineDelta(LineDelta), AddrDelta(&AddrDelta) {} + + /// \name Accessors + /// @{ + + int64_t getLineDelta() const { return LineDelta; } + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Dwarf; + } +}; + +class MCDwarfCallFrameFragment : public 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; + +public: + MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<8, 1>(FT_DwarfFrame, false, Sec), + AddrDelta(&AddrDelta) {} + + /// \name Accessors + /// @{ + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_DwarfFrame; + } +}; + +/// Represents a symbol table index fragment. +class MCSymbolIdFragment : public MCFragment { + const MCSymbol *Sym; + +public: + MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr) + : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {} + + /// \name Accessors + /// @{ + + const MCSymbol *getSymbol() { return Sym; } + const MCSymbol *getSymbol() const { return Sym; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_SymbolId; + } +}; + +/// Fragment representing the binary annotations produced by the +/// .cv_inline_linetable directive. +class MCCVInlineLineTableFragment : public MCFragment { + unsigned SiteFuncId; + unsigned StartFileId; + unsigned StartLineNum; + const MCSymbol *FnStartSym; + const MCSymbol *FnEndSym; + SmallString<8> Contents; + + /// CodeViewContext has the real knowledge about this format, so let it access + /// our members. + friend class CodeViewContext; + +public: + MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId, + unsigned StartLineNum, const MCSymbol *FnStartSym, + const MCSymbol *FnEndSym, + MCSection *Sec = nullptr) + : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId), + StartFileId(StartFileId), StartLineNum(StartLineNum), + FnStartSym(FnStartSym), FnEndSym(FnEndSym) {} + + /// \name Accessors + /// @{ + + const MCSymbol *getFnStartSym() const { return FnStartSym; } + const MCSymbol *getFnEndSym() const { return FnEndSym; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_CVInlineLines; + } +}; + +/// Fragment representing the .cv_def_range directive. +class MCCVDefRangeFragment : public MCEncodedFragmentWithFixups<32, 4> { + SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 2> Ranges; + SmallString<32> FixedSizePortion; + + /// CodeViewContext has the real knowledge about this format, so let it access + /// our members. + friend class CodeViewContext; + +public: + MCCVDefRangeFragment( + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, + StringRef FixedSizePortion, MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<32, 4>(FT_CVDefRange, false, Sec), + Ranges(Ranges.begin(), Ranges.end()), + FixedSizePortion(FixedSizePortion) {} + + /// \name Accessors + /// @{ + ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> getRanges() const { + return Ranges; + } + + StringRef getFixedSizePortion() const { return FixedSizePortion; } + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_CVDefRange; + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCFRAGMENT_H diff --git a/third_party/llvm-project/include/llvm/MC/MCInst.h b/third_party/llvm-project/include/llvm/MC/MCInst.h new file mode 100644 index 000000000..8df8096bb --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/MCInst.h @@ -0,0 +1,225 @@ +//===- llvm/MC/MCInst.h - MCInst class --------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCInst and MCOperand classes, which +// is the basic representation used to represent low-level machine code +// instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINST_H +#define LLVM_MC_MCINST_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" +#include <cassert> +#include <cstddef> +#include <cstdint> + +namespace llvm { + +class MCExpr; +class MCInst; +class MCInstPrinter; +class raw_ostream; + +/// Instances of this class represent operands of the MCInst class. +/// This is a simple discriminated union. +class MCOperand { + enum MachineOperandType : unsigned char { + kInvalid, ///< Uninitialized. + kRegister, ///< Register operand. + kImmediate, ///< Immediate operand. + kFPImmediate, ///< Floating-point immediate operand. + kExpr, ///< Relocatable immediate operand. + kInst ///< Sub-instruction operand. + }; + MachineOperandType Kind = kInvalid; + + union { + unsigned RegVal; + int64_t ImmVal; + double FPImmVal; + const MCExpr *ExprVal; + const MCInst *InstVal; + }; + +public: + MCOperand() : FPImmVal(0.0) {} + + bool isValid() const { return Kind != kInvalid; } + bool isReg() const { return Kind == kRegister; } + bool isImm() const { return Kind == kImmediate; } + bool isFPImm() const { return Kind == kFPImmediate; } + bool isExpr() const { return Kind == kExpr; } + bool isInst() const { return Kind == kInst; } + + /// Returns the register number. + unsigned getReg() const { + assert(isReg() && "This is not a register operand!"); + return RegVal; + } + + /// Set the register number. + void setReg(unsigned Reg) { + assert(isReg() && "This is not a register operand!"); + RegVal = Reg; + } + + int64_t getImm() const { + assert(isImm() && "This is not an immediate"); + return ImmVal; + } + + void setImm(int64_t Val) { + assert(isImm() && "This is not an immediate"); + ImmVal = Val; + } + + double getFPImm() const { + assert(isFPImm() && "This is not an FP immediate"); + return FPImmVal; + } + + void setFPImm(double Val) { + assert(isFPImm() && "This is not an FP immediate"); + FPImmVal = Val; + } + + const MCExpr *getExpr() const { + assert(isExpr() && "This is not an expression"); + return ExprVal; + } + + void setExpr(const MCExpr *Val) { + assert(isExpr() && "This is not an expression"); + ExprVal = Val; + } + + const MCInst *getInst() const { + assert(isInst() && "This is not a sub-instruction"); + return InstVal; + } + + void setInst(const MCInst *Val) { + assert(isInst() && "This is not a sub-instruction"); + InstVal = Val; + } + + static MCOperand createReg(unsigned Reg) { + MCOperand Op; + Op.Kind = kRegister; + Op.RegVal = Reg; + return Op; + } + + static MCOperand createImm(int64_t Val) { + MCOperand Op; + Op.Kind = kImmediate; + Op.ImmVal = Val; + return Op; + } + + static MCOperand createFPImm(double Val) { + MCOperand Op; + Op.Kind = kFPImmediate; + Op.FPImmVal = Val; + return Op; + } + + static MCOperand createExpr(const MCExpr *Val) { + MCOperand Op; + Op.Kind = kExpr; + Op.ExprVal = Val; + return Op; + } + + static MCOperand createInst(const MCInst *Val) { + MCOperand Op; + Op.Kind = kInst; + Op.InstVal = Val; + return Op; + } + + void print(raw_ostream &OS) const; + void dump() const; + bool isBareSymbolRef() const; + bool evaluateAsConstantImm(int64_t &Imm) const; +}; + +/// Instances of this class represent a single low-level machine +/// instruction. +class MCInst { + unsigned Opcode = 0; + SMLoc Loc; + SmallVector<MCOperand, 8> Operands; + // These flags could be used to pass some info from one target subcomponent + // to another, for example, from disassembler to asm printer. The values of + // the flags have any sense on target level only (e.g. prefixes on x86). + unsigned Flags = 0; + +public: + MCInst() = default; + + void setOpcode(unsigned Op) { Opcode = Op; } + unsigned getOpcode() const { return Opcode; } + + void setFlags(unsigned F) { Flags = F; } + unsigned getFlags() const { return Flags; } + + void setLoc(SMLoc loc) { Loc = loc; } + SMLoc getLoc() const { return Loc; } + + const MCOperand &getOperand(unsigned i) const { return Operands[i]; } + MCOperand &getOperand(unsigned i) { return Operands[i]; } + unsigned getNumOperands() const { return Operands.size(); } + + void addOperand(const MCOperand &Op) { Operands.push_back(Op); } + + using iterator = SmallVectorImpl<MCOperand>::iterator; + using const_iterator = SmallVectorImpl<MCOperand>::const_iterator; + + void clear() { Operands.clear(); } + void erase(iterator I) { Operands.erase(I); } + void erase(iterator First, iterator Last) { Operands.erase(First, Last); } + size_t size() const { return Operands.size(); } + iterator begin() { return Operands.begin(); } + const_iterator begin() const { return Operands.begin(); } + iterator end() { return Operands.end(); } + const_iterator end() const { return Operands.end(); } + + iterator insert(iterator I, const MCOperand &Op) { + return Operands.insert(I, Op); + } + + void print(raw_ostream &OS) const; + void dump() const; + + /// 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 MCInstPrinter *Printer = nullptr, + StringRef Separator = " ") const; + void dump_pretty(raw_ostream &OS, StringRef Name, + StringRef Separator = " ") const; +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { + MO.print(OS); + return OS; +} + +inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { + MI.print(OS); + return OS; +} + +} // end namespace llvm + +#endif // LLVM_MC_MCINST_H diff --git a/third_party/llvm-project/include/llvm/MC/MCRegister.h b/third_party/llvm-project/include/llvm/MC/MCRegister.h new file mode 100644 index 000000000..8372947a4 --- /dev/null +++ b/third_party/llvm-project/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/third_party/llvm-project/include/llvm/MC/MCRegisterInfo.h b/third_party/llvm-project/include/llvm/MC/MCRegisterInfo.h new file mode 100644 index 000000000..c7dc56ea5 --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/MCRegisterInfo.h @@ -0,0 +1,721 @@ +//===- MC/MCRegisterInfo.h - Target Register Description --------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file describes an abstract interface used to get information about a +// target machines register file. This information is used for a variety of +// purposed, especially register allocation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCREGISTERINFO_H +#define LLVM_MC_MCREGISTERINFO_H + +#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 { + +/// MCRegisterClass - Base class of TargetRegisterClass. +class MCRegisterClass { +public: + using iterator = const MCPhysReg*; + using const_iterator = const MCPhysReg*; + + const iterator RegsBegin; + const uint8_t *const RegSet; + const uint32_t NameIdx; + const uint16_t RegsSize; + const uint16_t RegSetSize; + const uint16_t ID; + const int8_t CopyCost; + const bool Allocatable; + + /// getID() - Return the register class ID number. + /// + unsigned getID() const { return ID; } + + /// begin/end - Return all of the registers in this class. + /// + iterator begin() const { return RegsBegin; } + iterator end() const { return RegsBegin + RegsSize; } + + /// getNumRegs - Return the number of registers in this class. + /// + unsigned getNumRegs() const { return RegsSize; } + + /// getRegister - Return the specified register in the class. + /// + unsigned getRegister(unsigned i) const { + assert(i < getNumRegs() && "Register number out of range!"); + return RegsBegin[i]; + } + + /// contains - Return true if the specified register is included in this + /// register class. This does not include virtual registers. + 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(MCRegister Reg1, MCRegister Reg2) const { + return contains(Reg1) && contains(Reg2); + } + + /// getCopyCost - Return the cost of copying a value between two registers in + /// this class. A negative number means the register class is very expensive + /// to copy e.g. status flag register classes. + int getCopyCost() const { return CopyCost; } + + /// isAllocatable - Return true if this register class may be used to create + /// virtual registers. + bool isAllocatable() const { return Allocatable; } +}; + +/// MCRegisterDesc - This record contains information about a particular +/// register. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers +/// of AX. The SuperRegs field is a zero terminated array of registers that are +/// super-registers of the specific register, e.g. RAX, EAX, are +/// super-registers of AX. +/// +struct MCRegisterDesc { + uint32_t Name; // Printable name for the reg (for debugging) + uint32_t SubRegs; // Sub-register set, described above + uint32_t SuperRegs; // Super-register set, described above + + // Offset into MCRI::SubRegIndices of a list of sub-register indices for each + // sub-register in SubRegs. + uint32_t SubRegIndices; + + // RegUnits - Points to the list of register units. The low 4 bits holds the + // Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator. + uint32_t RegUnits; + + /// Index into list with lane mask sequences. The sequence contains a lanemask + /// for every register unit. + uint16_t RegUnitLaneMasks; +}; + +/// MCRegisterInfo base class - We assume that the target defines a static +/// array of MCRegisterDesc objects that represent all of the machine +/// registers that the target has. As such, we simply have to track a pointer +/// to this array so that we can turn register number into a register +/// descriptor. +/// +/// Note this class is designed to be a base class of TargetRegisterInfo, which +/// is the interface used by codegen. However, specific targets *should never* +/// specialize this class. MCRegisterInfo should only contain getters to access +/// TableGen generated physical register data. It must not be extended with +/// virtual methods. +/// +class MCRegisterInfo { +public: + using regclass_iterator = const MCRegisterClass *; + + /// DwarfLLVMRegPair - Emitted by tablegen so Dwarf<->LLVM reg mappings can be + /// performed with a binary search. + struct DwarfLLVMRegPair { + unsigned FromReg; + unsigned ToReg; + + bool operator<(DwarfLLVMRegPair RHS) const { return FromReg < RHS.FromReg; } + }; + + /// SubRegCoveredBits - Emitted by tablegen: bit range covered by a subreg + /// index, -1 in any being invalid. + struct SubRegCoveredBits { + uint16_t Offset; + uint16_t Size; + }; + +private: + const MCRegisterDesc *Desc; // Pointer to the descriptor array + unsigned NumRegs; // Number of entries in the array + 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. + const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table. + const MCPhysReg *DiffLists; // Pointer to the difflists array + const LaneBitmask *RegUnitMaskSequences; // Pointer to lane mask sequences + // for register units. + const char *RegStrings; // Pointer to the string table. + const char *RegClassStrings; // Pointer to the class strings. + const uint16_t *SubRegIndices; // Pointer to the subreg lookup + // array. + const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered + // bit ranges array. + unsigned NumSubRegIndices; // Number of subreg indices. + const uint16_t *RegEncodingTable; // Pointer to array of register + // encodings. + + unsigned L2DwarfRegsSize; + unsigned EHL2DwarfRegsSize; + unsigned Dwarf2LRegsSize; + unsigned EHDwarf2LRegsSize; + const DwarfLLVMRegPair *L2DwarfRegs; // LLVM to Dwarf regs mapping + 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<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 + /// differentially encoded register and regunit lists in DiffLists. + /// Don't use this class directly, use one of the specialized sub-classes + /// defined below. + class DiffListIterator { + uint16_t Val = 0; + const MCPhysReg *List = nullptr; + + protected: + /// Create an invalid iterator. Call init() to point to something useful. + DiffListIterator() = default; + + /// init - Point the iterator to InitVal, decoding subsequent values from + /// DiffList. The iterator will initially point to InitVal, sub-classes are + /// responsible for skipping the seed value if it is not part of the list. + void init(MCPhysReg InitVal, const MCPhysReg *DiffList) { + Val = InitVal; + List = DiffList; + } + + /// 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). + MCRegister advance() { + assert(isValid() && "Cannot move off the end of the list."); + MCPhysReg D = *List++; + Val += D; + return D; + } + + public: + /// isValid - returns true if this iterator is not yet at the end. + bool isValid() const { return List; } + + /// Dereference the iterator to get the value at the current position. + MCRegister operator*() const { return Val; } + + /// Pre-increment to move to the next position. + void operator++() { + // The end of the list is encoded as a 0 differential. + if (!advance()) + List = nullptr; + } + }; + + // These iterators are allowed to sub-class DiffListIterator and access + // internal list pointers. + friend class MCSubRegIterator; + friend class MCSubRegIndexIterator; + friend class MCSuperRegIterator; + friend class MCRegUnitIterator; + friend class MCRegUnitMaskIterator; + friend class MCRegUnitRootIterator; + + /// Initialize MCRegisterInfo, called by TableGen + /// auto-generated routines. *DO NOT USE*. + void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, + unsigned PC, + const MCRegisterClass *C, unsigned NC, + const MCPhysReg (*RURoots)[2], + unsigned NRU, + const MCPhysReg *DL, + const LaneBitmask *RUMS, + const char *Strings, + const char *ClassStrings, + const uint16_t *SubIndices, + unsigned NumIndices, + const SubRegCoveredBits *SubIdxRanges, + const uint16_t *RET) { + Desc = D; + NumRegs = NR; + RAReg = RA; + PCReg = PC; + Classes = C; + DiffLists = DL; + RegUnitMaskSequences = RUMS; + RegStrings = Strings; + RegClassStrings = ClassStrings; + NumClasses = NC; + RegUnitRoots = RURoots; + NumRegUnits = NRU; + SubRegIndices = SubIndices; + NumSubRegIndices = NumIndices; + SubRegIdxRanges = SubIdxRanges; + RegEncodingTable = RET; + + // Initialize DWARF register mapping variables + EHL2DwarfRegs = nullptr; + EHL2DwarfRegsSize = 0; + L2DwarfRegs = nullptr; + L2DwarfRegsSize = 0; + EHDwarf2LRegs = nullptr; + EHDwarf2LRegsSize = 0; + Dwarf2LRegs = nullptr; + Dwarf2LRegsSize = 0; + } + + /// Used to initialize LLVM register to Dwarf + /// register number mapping. Called by TableGen auto-generated routines. + /// *DO NOT USE*. + void mapLLVMRegsToDwarfRegs(const DwarfLLVMRegPair *Map, unsigned Size, + bool isEH) { + if (isEH) { + EHL2DwarfRegs = Map; + EHL2DwarfRegsSize = Size; + } else { + L2DwarfRegs = Map; + L2DwarfRegsSize = Size; + } + } + + /// Used to initialize Dwarf register to LLVM + /// register number mapping. Called by TableGen auto-generated routines. + /// *DO NOT USE*. + void mapDwarfRegsToLLVMRegs(const DwarfLLVMRegPair *Map, unsigned Size, + bool isEH) { + if (isEH) { + EHDwarf2LRegs = Map; + EHDwarf2LRegsSize = Size; + } else { + Dwarf2LRegs = Map; + Dwarf2LRegsSize = Size; + } + } + + /// mapLLVMRegToSEHReg - Used to initialize LLVM register to SEH register + /// number mapping. By default the SEH register number is just the same + /// as the LLVM register number. + /// FIXME: TableGen these numbers. Currently this requires target specific + /// initialization code. + void mapLLVMRegToSEHReg(MCRegister LLVMReg, int SEHReg) { + L2SEHRegs[LLVMReg] = SEHReg; + } + + void mapLLVMRegToCVReg(MCRegister LLVMReg, int CVReg) { + L2CVRegs[LLVMReg] = CVReg; + } + + /// This method should return the register where the return + /// address can be found. + MCRegister getRARegister() const { + return RAReg; + } + + /// Return the register which is the program counter. + MCRegister getProgramCounter() const { + return PCReg; + } + + const MCRegisterDesc &operator[](MCRegister RegNo) const { + assert(RegNo < NumRegs && + "Attempting to access record for invalid register number!"); + return Desc[RegNo]; + } + + /// Provide a get method, equivalent to [], but more useful with a + /// pointer to this object. + 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. + 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. + 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(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. + /// If the index is used to access subregisters of different sizes, return -1. + unsigned getSubRegIdxSize(unsigned Idx) const; + + /// Get the offset of the bit range covered by a sub-register index. + /// If an Offset doesn't make sense (the index isn't continuous, or is used to + /// access sub-registers at different offsets), return -1. + unsigned getSubRegIdxOffset(unsigned Idx) const; + + /// Return the human-readable symbolic target-specific name for the + /// specified physical register. + const char *getName(MCRegister RegNo) const { + return RegStrings + get(RegNo).Name; + } + + /// Return the number of registers this target has (useful for + /// sizing arrays holding per register information) + unsigned getNumRegs() const { + return NumRegs; + } + + /// Return the number of sub-register indices + /// understood by the target. Index 0 is reserved for the no-op sub-register, + /// while 1 to getNumSubRegIndices() - 1 represent real sub-registers. + unsigned getNumSubRegIndices() const { + return NumSubRegIndices; + } + + /// Return the number of (native) register units in the + /// target. Register units are numbered from 0 to getNumRegUnits() - 1. They + /// can be accessed through MCRegUnitIterator defined below. + unsigned getNumRegUnits() const { + return NumRegUnits; + } + + /// Map a target register to an equivalent dwarf register + /// 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(MCRegister RegNum, bool isEH) 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. + int getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const; + + /// Map a target register to an equivalent SEH register + /// number. Returns LLVM register number if there is no equivalent value. + int getSEHRegNum(MCRegister RegNum) const; + + /// Map a target register to an equivalent CodeView register + /// number. + int getCodeViewRegNum(MCRegister RegNum) const; + + regclass_iterator regclass_begin() const { return Classes; } + regclass_iterator regclass_end() const { return Classes+NumClasses; } + iterator_range<regclass_iterator> regclasses() const { + return make_range(regclass_begin(), regclass_end()); + } + + unsigned getNumRegClasses() const { + return (unsigned)(regclass_end()-regclass_begin()); + } + + /// Returns the register class associated with the enumeration + /// value. See class MCOperandInfo. + const MCRegisterClass& getRegClass(unsigned i) const { + assert(i < getNumRegClasses() && "Register Class ID out of range"); + return Classes[i]; + } + + const char *getRegClassName(const MCRegisterClass *Class) const { + return RegClassStrings + Class->NameIdx; + } + + /// Returns the encoding for RegNo + 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(MCRegister RegA, MCRegister RegB) const { + return isSuperRegister(RegB, RegA); + } + + /// Returns true if RegB is a super-register of RegA. + bool isSuperRegister(MCRegister RegA, MCRegister RegB) const; + + /// Returns true if RegB is a sub-register of RegA or if RegB == RegA. + 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(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(MCRegister RegA, MCRegister RegB) const { + return isSubRegisterEq(RegA, RegB) || isSuperRegister(RegA, RegB); + } +}; + +//===----------------------------------------------------------------------===// +// Register List Iterators +//===----------------------------------------------------------------------===// + +// MCRegisterInfo provides lists of super-registers, sub-registers, and +// aliasing registers. Use these iterator classes to traverse the lists. + +/// MCSubRegIterator enumerates all sub-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. +class MCSubRegIterator : public MCRegisterInfo::DiffListIterator { +public: + 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) + ++*this; + } +}; + +/// Iterator that enumerates the sub-registers of a Reg and the associated +/// sub-register indices. +class MCSubRegIndexIterator { + MCSubRegIterator SRIter; + const uint16_t *SRIndex; + +public: + /// Constructs an iterator that traverses subregisters and their + /// associated subregister indices. + MCSubRegIndexIterator(MCRegister Reg, const MCRegisterInfo *MCRI) + : SRIter(Reg, MCRI) { + SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices; + } + + /// Returns current sub-register. + MCRegister getSubReg() const { + return *SRIter; + } + + /// Returns sub-register index of the current sub-register. + unsigned getSubRegIndex() const { + return *SRIndex; + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return SRIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++SRIter; + ++SRIndex; + } +}; + +/// MCSuperRegIterator enumerates all super-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. +class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { +public: + MCSuperRegIterator() = default; + + MCSuperRegIterator(MCRegister Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { + init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs); + // Initially, the iterator points to Reg itself. + if (!IncludeSelf) + ++*this; + } +}; + +// 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(MCRegister RegA, MCRegister RegB) const{ + for (MCSuperRegIterator I(RegA, this); I.isValid(); ++I) + if (*I == RegB) + return true; + return false; +} + +//===----------------------------------------------------------------------===// +// Register Units +//===----------------------------------------------------------------------===// + +// Register units are used to compute register aliasing. Every register has at +// least one register unit, but it can have more. Two registers overlap if and +// only if they have a common register unit. +// +// A target with a complicated sub-register structure will typically have many +// fewer register units than actual registers. MCRI::getNumRegUnits() returns +// the number of register units in the target. + +// MCRegUnitIterator enumerates a list of register units for Reg. The list is +// in ascending numerical order. +class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator { +public: + /// MCRegUnitIterator - Create an iterator that traverses the register units + /// in Reg. + MCRegUnitIterator() = default; + + MCRegUnitIterator(MCRegister Reg, const MCRegisterInfo *MCRI) { + assert(Reg && "Null register has no regunits"); + // Decode the RegUnits MCRegisterDesc field. + unsigned RU = MCRI->get(Reg).RegUnits; + unsigned Scale = RU & 15; + unsigned Offset = RU >> 4; + + // Initialize the iterator to Reg * Scale, and the List pointer to + // DiffLists + Offset. + init(Reg * Scale, MCRI->DiffLists + Offset); + + // That may not be a valid unit, we need to advance by one to get the real + // unit number. The first differential can be 0 which would normally + // terminate the list, but since we know every register has at least one + // unit, we can allow a 0 differential here. + advance(); + } +}; + +/// MCRegUnitMaskIterator enumerates a list of register units and their +/// associated lane masks for Reg. The register units are in ascending +/// numerical order. +class MCRegUnitMaskIterator { + MCRegUnitIterator RUIter; + const LaneBitmask *MaskListIter; + +public: + MCRegUnitMaskIterator() = default; + + /// Constructs an iterator that traverses the register units and their + /// associated LaneMasks in Reg. + MCRegUnitMaskIterator(MCRegister Reg, const MCRegisterInfo *MCRI) + : RUIter(Reg, MCRI) { + uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks; + MaskListIter = &MCRI->RegUnitMaskSequences[Idx]; + } + + /// Returns a (RegUnit, LaneMask) pair. + std::pair<unsigned,LaneBitmask> operator*() const { + return std::make_pair(*RUIter, *MaskListIter); + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return RUIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++MaskListIter; + ++RUIter; + } +}; + +// Each register unit has one or two root registers. The complete set of +// registers containing a register unit is the union of the roots and their +// super-registers. All registers aliasing Unit can be visited like this: +// +// for (MCRegUnitRootIterator RI(Unit, MCRI); RI.isValid(); ++RI) { +// for (MCSuperRegIterator SI(*RI, MCRI, true); SI.isValid(); ++SI) +// visit(*SI); +// } + +/// MCRegUnitRootIterator enumerates the root registers of a register unit. +class MCRegUnitRootIterator { + uint16_t Reg0 = 0; + uint16_t Reg1 = 0; + +public: + MCRegUnitRootIterator() = default; + + MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) { + assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit"); + Reg0 = MCRI->RegUnitRoots[RegUnit][0]; + Reg1 = MCRI->RegUnitRoots[RegUnit][1]; + } + + /// Dereference to get the current root register. + unsigned operator*() const { + return Reg0; + } + + /// Check if the iterator is at the end of the list. + bool isValid() const { + return Reg0; + } + + /// Preincrement to move to the next root register. + void operator++() { + assert(isValid() && "Cannot move off the end of the list."); + Reg0 = Reg1; + Reg1 = 0; + } +}; + +/// MCRegAliasIterator enumerates all registers aliasing Reg. If IncludeSelf is +/// set, Reg itself is included in the list. This iterator does not guarantee +/// any ordering or that entries are unique. +class MCRegAliasIterator { +private: + MCRegister Reg; + const MCRegisterInfo *MCRI; + bool IncludeSelf; + + MCRegUnitIterator RI; + MCRegUnitRootIterator RRI; + MCSuperRegIterator SI; + +public: + MCRegAliasIterator(MCRegister Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf) + : Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) { + // Initialize the iterators. + for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) { + for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) { + for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) { + if (!(!IncludeSelf && Reg == *SI)) + return; + } + } + } + } + + bool isValid() const { return RI.isValid(); } + + MCRegister operator*() const { + assert(SI.isValid() && "Cannot dereference an invalid iterator."); + return *SI; + } + + void advance() { + // Assuming SI is valid. + ++SI; + if (SI.isValid()) return; + + ++RRI; + if (RRI.isValid()) { + SI = MCSuperRegIterator(*RRI, MCRI, true); + return; + } + + ++RI; + if (RI.isValid()) { + RRI = MCRegUnitRootIterator(*RI, MCRI); + SI = MCSuperRegIterator(*RRI, MCRI, true); + } + } + + void operator++() { + assert(isValid() && "Cannot move off the end of the list."); + do advance(); + while (!IncludeSelf && isValid() && *SI == Reg); + } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCREGISTERINFO_H diff --git a/third_party/llvm-project/include/llvm/MC/MCSymbol.h b/third_party/llvm-project/include/llvm/MC/MCSymbol.h new file mode 100644 index 000000000..189484dea --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/MCSymbol.h @@ -0,0 +1,441 @@ +//===- MCSymbol.h - Machine Code Symbols ------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCSymbol class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSYMBOL_H +#define LLVM_MC_MCSYMBOL_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <cstddef> +#include <cstdint> + +namespace llvm { + +class MCAsmInfo; +class MCContext; +class MCExpr; +class MCSection; +class raw_ostream; + +/// 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 { +protected: + /// The kind of the symbol. If it is any value other than unset then this + /// class is actually one of the appropriate subclasses of MCSymbol. + enum SymbolKind { + SymbolKindUnset, + SymbolKindCOFF, + SymbolKindELF, + SymbolKindMachO, + SymbolKindWasm, + SymbolKindXCOFF, + }; + + /// A symbol can contain an Offset, or Value, or be Common, but never more + /// than one of these. + enum Contents : uint8_t { + SymContentsUnset, + SymContentsOffset, + SymContentsVariable, + SymContentsCommon, + SymContentsTargetCommon, // Index stores the section index + }; + + // Special sentinal value for the absolute pseudo fragment. + static MCFragment *AbsolutePseudoFragment; + + /// If a symbol has a Fragment, the section is implied, so we only need + /// one pointer. + /// The special AbsolutePseudoFragment value is for absolute symbols. + /// If this is a variable symbol, this caches the variable value's fragment. + /// FIXME: We might be able to simplify this by having the asm streamer create + /// dummy fragments. + /// If this is a section, then it gives the symbol is defined in. This is null + /// for undefined symbols. + /// + /// If this is a fragment, then it gives the fragment this symbol's value is + /// relative to, if any. + /// + /// For the 'HasName' integer, this is true if this symbol is named. + /// A named symbol will have a pointer to the name allocated in the bytes + /// immediately prior to the MCSymbol. + mutable PointerIntPair<MCFragment *, 1> FragmentAndHasName; + + /// 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; + + /// True if this symbol can be redefined. + unsigned IsRedefinable : 1; + + /// IsUsed - True if this symbol has been used. + mutable unsigned IsUsed : 1; + + mutable unsigned IsRegistered : 1; + + /// This symbol is visible outside this translation unit. + mutable unsigned IsExternal : 1; + + /// This symbol is private extern. + mutable unsigned IsPrivateExtern : 1; + + /// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is + /// unsigned to avoid sign extension and achieve better bitpacking with MSVC. + unsigned Kind : 3; + + /// True if we have created a relocation that uses this symbol. + mutable unsigned IsUsedInReloc : 1; + + /// This is actually a Contents enumerator, but is unsigned to avoid sign + /// extension and achieve better bitpacking with MSVC. + unsigned SymbolContents : 3; + + /// The alignment of the symbol, if it is 'common', or -1. + /// + /// The alignment is stored as log2(align) + 1. This allows all values from + /// 0 to 2^31 to be stored which is every power of 2 representable by an + /// unsigned. + enum : unsigned { NumCommonAlignmentBits = 5 }; + unsigned CommonAlignLog2 : NumCommonAlignmentBits; + + /// The Flags field is used by object file implementations to store + /// additional per symbol information which is not easily classified. + enum : unsigned { NumFlagsBits = 16 }; + mutable uint32_t Flags : NumFlagsBits; + + /// Index field, for use by the object file implementation. + mutable uint32_t Index = 0; + + union { + /// The offset to apply to the fragment address to form this symbol's value. + uint64_t Offset; + + /// The size of the symbol, if it is 'common'. + uint64_t CommonSize; + + /// If non-null, the value for a variable symbol. + const MCExpr *Value; + }; + + // MCContext creates and uniques these. + friend class MCExpr; + friend class MCContext; + + /// The name for a symbol. + /// MCSymbol contains a uint64_t so is probably aligned to 8. On a 32-bit + /// system, the name is a pointer so isn't going to satisfy the 8 byte + /// alignment of uint64_t. Account for that here. + using NameEntryStorageTy = union { + const StringMapEntry<bool> *NameEntry; + uint64_t AlignmentPadding; + }; + + MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary) + : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false), + IsRegistered(false), IsExternal(false), IsPrivateExtern(false), + Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset), + CommonAlignLog2(0), Flags(0) { + Offset = 0; + FragmentAndHasName.setInt(!!Name); + if (Name) + getNameEntryPtr() = Name; + } + + // Provide custom new/delete as we will only allocate space for a name + // if we need one. + void *operator new(size_t s, const StringMapEntry<bool> *Name, + MCContext &Ctx); + +private: + void operator delete(void *); + /// Placement delete - required by std, but never called. + void operator delete(void*, unsigned) { + llvm_unreachable("Constructor throws?"); + } + /// Placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + llvm_unreachable("Constructor throws?"); + } + + MCSection *getSectionPtr() const { + if (MCFragment *F = getFragment()) { + assert(F != AbsolutePseudoFragment); + return F->getParent(); + } + return nullptr; + } + + /// Get a reference to the name field. Requires that we have a name + const StringMapEntry<bool> *&getNameEntryPtr() { + assert(FragmentAndHasName.getInt() && "Name is required"); + NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this); + return (*(Name - 1)).NameEntry; + } + const StringMapEntry<bool> *&getNameEntryPtr() const { + return const_cast<MCSymbol*>(this)->getNameEntryPtr(); + } + +public: + MCSymbol(const MCSymbol &) = delete; + MCSymbol &operator=(const MCSymbol &) = delete; + + /// getName - Get the symbol name. + StringRef getName() const { + if (!FragmentAndHasName.getInt()) + return StringRef(); + + return getNameEntryPtr()->first(); + } + + bool isRegistered() const { return IsRegistered; } + void setIsRegistered(bool Value) const { IsRegistered = Value; } + + void setUsedInReloc() const { IsUsedInReloc = true; } + bool isUsedInReloc() const { return IsUsedInReloc; } + + /// \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; } + + /// Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + if (SymbolContents == SymContentsVariable) { + Value = nullptr; + SymbolContents = SymContentsUnset; + } + setUndefined(); + IsRedefinable = false; + } + } + + /// @} + /// \name Associated Sections + /// @{ + + /// 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 !isUndefined(); } + + /// isInSection - Check if this symbol is defined in some section (i.e., it + /// is defined but not absolute). + bool isInSection() const { + return isDefined() && !isAbsolute(); + } + + /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). + bool isUndefined(bool SetUsed = true) const { + return getFragment(SetUsed) == nullptr; + } + + /// isAbsolute - Check if this is an absolute symbol. + bool isAbsolute() const { + return getFragment() == AbsolutePseudoFragment; + } + + /// 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 fragment \p F. + void setFragment(MCFragment *F) const { + assert(!isVariable() && "Cannot set fragment of variable"); + FragmentAndHasName.setPointer(F); + } + + /// Mark the symbol as undefined. + void setUndefined() { FragmentAndHasName.setPointer(nullptr); } + + bool isELF() const { return Kind == SymbolKindELF; } + + bool isCOFF() const { return Kind == SymbolKindCOFF; } + + bool isMachO() const { return Kind == SymbolKindMachO; } + + bool isWasm() const { return Kind == SymbolKindWasm; } + + bool isXCOFF() const { return Kind == SymbolKindXCOFF; } + + /// @} + /// \name Variable Symbols + /// @{ + + /// isVariable - Check if this is a variable symbol. + bool isVariable() const { + return SymbolContents == SymContentsVariable; + } + + /// getVariableValue - Get the value for variable symbols. + const MCExpr *getVariableValue(bool SetUsed = true) const { + assert(isVariable() && "Invalid accessor!"); + IsUsed |= SetUsed; + return Value; + } + + void setVariableValue(const MCExpr *Value); + + /// @} + + /// Get the (implementation defined) index. + uint32_t getIndex() const { + return Index; + } + + /// Set the (implementation defined) index. + void setIndex(uint32_t Value) const { + Index = Value; + } + + bool isUnset() const { return SymbolContents == SymContentsUnset; } + + uint64_t getOffset() const { + assert((SymbolContents == SymContentsUnset || + SymbolContents == SymContentsOffset) && + "Cannot get offset for a common/variable symbol"); + return Offset; + } + void setOffset(uint64_t Value) { + assert((SymbolContents == SymContentsUnset || + SymbolContents == SymContentsOffset) && + "Cannot set offset for a common/variable symbol"); + Offset = Value; + SymbolContents = SymContentsOffset; + } + + /// Return the size of a 'common' symbol. + uint64_t getCommonSize() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonSize; + } + + /// Mark this symbol as being 'common'. + /// + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + /// \param Target - Is the symbol a target-specific common-like symbol. + void setCommon(uint64_t Size, unsigned Align, bool Target = false) { + assert(getOffset() == 0); + CommonSize = Size; + SymbolContents = Target ? SymContentsTargetCommon : SymContentsCommon; + + assert((!Align || isPowerOf2_32(Align)) && + "Alignment must be a power of 2"); + unsigned Log2Align = Log2_32(Align) + 1; + assert(Log2Align < (1U << NumCommonAlignmentBits) && + "Out of range alignment"); + CommonAlignLog2 = Log2Align; + } + + /// Return the alignment of a 'common' symbol. + unsigned getCommonAlignment() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1)) : 0; + } + + /// Declare this symbol as being 'common'. + /// + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + /// \param Target - Is the symbol a target-specific common-like symbol. + /// \return True if symbol was already declared as a different type + bool declareCommon(uint64_t Size, unsigned Align, bool Target = false) { + assert(isCommon() || getOffset() == 0); + if(isCommon()) { + if (CommonSize != Size || getCommonAlignment() != Align || + isTargetCommon() != Target) + return true; + } else + setCommon(Size, Align, Target); + return false; + } + + /// Is this a 'common' symbol. + bool isCommon() const { + return SymbolContents == SymContentsCommon || + SymbolContents == SymContentsTargetCommon; + } + + /// Is this a target-specific common-like symbol. + bool isTargetCommon() const { + return SymbolContents == SymContentsTargetCommon; + } + + MCFragment *getFragment(bool SetUsed = true) const { + MCFragment *Fragment = FragmentAndHasName.getPointer(); + if (Fragment || !isVariable()) + return Fragment; + Fragment = getVariableValue(SetUsed)->findAssociatedFragment(); + FragmentAndHasName.setPointer(Fragment); + return Fragment; + } + + bool isExternal() const { return IsExternal; } + void setExternal(bool Value) const { IsExternal = Value; } + + bool isPrivateExtern() const { return IsPrivateExtern; } + void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } + + /// print - Print the value to the stream \p OS. + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + + /// dump - Print the value to stderr. + void dump() const; + +protected: + /// Get the (implementation defined) symbol flags. + uint32_t getFlags() const { return Flags; } + + /// Set the (implementation defined) symbol flags. + void setFlags(uint32_t Value) const { + assert(Value < (1U << NumFlagsBits) && "Out of range flags"); + Flags = Value; + } + + /// Modify the flags via a mask + void modifyFlags(uint32_t Value, uint32_t Mask) const { + assert(Value < (1U << NumFlagsBits) && "Out of range flags"); + Flags = (Flags & ~Mask) | Value; + } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { + Sym.print(OS, nullptr); + return OS; +} + +} // end namespace llvm + +#endif // LLVM_MC_MCSYMBOL_H diff --git a/third_party/llvm-project/include/llvm/MC/MCSymbolWasm.h b/third_party/llvm-project/include/llvm/MC/MCSymbolWasm.h new file mode 100644 index 000000000..95beebe3f --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/MCSymbolWasm.h @@ -0,0 +1,110 @@ +//===- MCSymbolWasm.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_MCSYMBOLWASM_H +#define LLVM_MC_MCSYMBOLWASM_H + +#include "llvm/BinaryFormat/Wasm.h" +#include "llvm/MC/MCSymbol.h" + +namespace llvm { + +class MCSymbolWasm : public MCSymbol { + wasm::WasmSymbolType Type = wasm::WASM_SYMBOL_TYPE_DATA; + bool IsWeak = false; + bool IsHidden = false; + bool IsComdat = false; + mutable bool IsUsedInGOT = false; + Optional<std::string> ImportModule; + Optional<std::string> ImportName; + wasm::WasmSignature *Signature = nullptr; + Optional<wasm::WasmGlobalType> GlobalType; + Optional<wasm::WasmEventType> EventType; + + /// 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; + +public: + // Use a module name of "env" for now, for compatibility with existing tools. + // This is temporary, and may change, as the ABI is not yet stable. + MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary) + : MCSymbol(SymbolKindWasm, Name, isTemporary) {} + static bool classof(const MCSymbol *S) { return S->isWasm(); } + + const MCExpr *getSize() const { return SymbolSize; } + void setSize(const MCExpr *SS) { SymbolSize = SS; } + + bool isFunction() const { return Type == wasm::WASM_SYMBOL_TYPE_FUNCTION; } + bool isData() const { return Type == wasm::WASM_SYMBOL_TYPE_DATA; } + bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; } + bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; } + bool isEvent() const { return Type == wasm::WASM_SYMBOL_TYPE_EVENT; } + wasm::WasmSymbolType getType() const { return Type; } + void setType(wasm::WasmSymbolType type) { Type = type; } + + bool isExported() const { + return getFlags() & wasm::WASM_SYMBOL_EXPORTED; + } + void setExported() const { + 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; } + + bool isHidden() const { return IsHidden; } + void setHidden(bool isHidden) { IsHidden = isHidden; } + + bool isComdat() const { return IsComdat; } + void setComdat(bool isComdat) { IsComdat = isComdat; } + + const StringRef getImportModule() const { + if (ImportModule.hasValue()) { + return ImportModule.getValue(); + } + return "env"; + } + void setImportModule(StringRef Name) { ImportModule = Name; } + + const StringRef getImportName() const { + if (ImportName.hasValue()) { + return ImportName.getValue(); + } + return getName(); + } + void setImportName(StringRef Name) { ImportName = Name; } + + void setUsedInGOT() const { IsUsedInGOT = true; } + bool isUsedInGOT() const { return IsUsedInGOT; } + + const wasm::WasmSignature *getSignature() const { return Signature; } + void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; } + + const wasm::WasmGlobalType &getGlobalType() const { + assert(GlobalType.hasValue()); + return GlobalType.getValue(); + } + void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; } + + const wasm::WasmEventType &getEventType() const { + assert(EventType.hasValue()); + return EventType.getValue(); + } + void setEventType(wasm::WasmEventType ET) { EventType = ET; } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCSYMBOLWASM_H diff --git a/third_party/llvm-project/include/llvm/MC/SubtargetFeature.h b/third_party/llvm-project/include/llvm/MC/SubtargetFeature.h new file mode 100644 index 000000000..defbc3c64 --- /dev/null +++ b/third_party/llvm-project/include/llvm/MC/SubtargetFeature.h @@ -0,0 +1,236 @@ +//===- llvm/MC/SubtargetFeature.h - CPU characteristics ---------*- 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 +// +//===----------------------------------------------------------------------===// +// +/// \file Defines and manages user or tool specified CPU characteristics. +/// The intent is to be able to package specific features that should or should +/// not be used on a specific target processor. A tool, such as llc, could, as +/// as example, gather chip info from the command line, a long with features +/// that should be used on that chip. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_SUBTARGETFEATURE_H +#define LLVM_MC_SUBTARGETFEATURE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MathExtras.h" +#include <array> +#include <bitset> +#include <initializer_list> +#include <string> +#include <vector> + +namespace llvm { + +class raw_ostream; +class Triple; + +const unsigned MAX_SUBTARGET_WORDS = 3; +const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64; + +/// Container class for subtarget features. +/// 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]; + } + +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); + if (LHS != RHS) + return LHS < RHS; + } + return false; + } +}; + +/// Class used to store the subtarget bits in the tables created by tablegen. +class FeatureBitArray : public FeatureBitset { +public: + constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) + : FeatureBitset(B) {} + + const FeatureBitset &getAsBitset() const { return *this; } +}; + +//===----------------------------------------------------------------------===// + +/// Manages the enabling and disabling of subtarget specific features. +/// +/// Features are encoded as a string of the form +/// "+attr1,+attr2,-attr3,...,+attrN" +/// A comma separates each feature from the next (all lowercase.) +/// Each of the remaining features is prefixed with + or - indicating whether +/// that feature should be enabled or disabled contrary to the cpu +/// specification. +class SubtargetFeatures { + std::vector<std::string> Features; ///< Subtarget features as a vector + +public: + explicit SubtargetFeatures(StringRef Initial = ""); + + /// Returns features as a string. + std::string getString() const; + + /// Adds Features. + void AddFeature(StringRef String, bool Enable = true); + + /// Returns the vector of individual subtarget features. + const std::vector<std::string> &getFeatures() const { return Features; } + + /// Prints feature string. + void print(raw_ostream &OS) const; + + // Dumps feature info. + void dump() const; + + /// Adds the default features for the specified target triple. + void getDefaultSubtargetFeatures(const Triple& Triple); + + /// Determine if a feature has a flag; '+' or '-' + static bool hasFlag(StringRef Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' or '-' flag + return Ch == '+' || Ch =='-'; + } + + /// Return string stripped of flag. + static std::string StripFlag(StringRef Feature) { + return hasFlag(Feature) ? Feature.substr(1) : Feature; + } + + /// Return true if enable flag; '+'. + static inline bool isEnabled(StringRef Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' for enabled + return Ch == '+'; + } + + /// Splits a string of comma separated items in to a vector of strings. + static void Split(std::vector<std::string> &V, StringRef S); +}; + +} // end namespace llvm + +#endif // LLVM_MC_SUBTARGETFEATURE_H |