diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -34,7 +34,7 @@ /// needed for parsing. class MCExpr { public: - enum ExprKind { + enum ExprKind : uint8_t { Binary, ///< Binary expressions. Constant, ///< Constant expressions. SymbolRef, ///< References to labels and assigned expressions. @@ -43,7 +43,14 @@ }; private: + static const unsigned NumSubclassDataBits = 24; + static_assert( + NumSubclassDataBits == CHAR_BIT * (sizeof(unsigned) - sizeof(ExprKind)), + "ExprKind and SubclassData together should take up one word"); + ExprKind Kind; + /// Field reserved for use by MCExpr subclasses. + unsigned SubclassData : NumSubclassDataBits; SMLoc Loc; bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, @@ -51,13 +58,19 @@ const SectionAddrMap *Addrs, bool InSet) const; protected: - explicit MCExpr(ExprKind Kind, SMLoc Loc) : Kind(Kind), Loc(Loc) {} + explicit MCExpr(ExprKind Kind, SMLoc Loc, unsigned SubclassData = 0) + : Kind(Kind), SubclassData(SubclassData), Loc(Loc) { + assert(SubclassData < (1 << NumSubclassDataBits) && + "Subclass data too large"); + } bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const MCFixup *Fixup, const SectionAddrMap *Addrs, bool InSet) const; + unsigned getSubclassData() const { return SubclassData; } + public: MCExpr(const MCExpr &) = delete; MCExpr &operator=(const MCExpr &) = delete; @@ -130,19 +143,20 @@ //// Represent a constant integer expression. class MCConstantExpr : public MCExpr { int64_t Value; - bool PrintInHex = false; - unsigned SizeInBytes = 0; - explicit MCConstantExpr(int64_t Value) - : MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {} + // Subclass data stores SizeInBytes in bits 0..7 and PrintInHex in bit 8. + static const unsigned SizeInBytesBits = 8; + static const unsigned SizeInBytesMask = (1 << SizeInBytesBits) - 1; + static const unsigned PrintInHexBit = 1 << SizeInBytesBits; - MCConstantExpr(int64_t Value, bool PrintInHex) - : MCExpr(MCExpr::Constant, SMLoc()), Value(Value), - PrintInHex(PrintInHex) {} + static unsigned encodeSubclassData(bool PrintInHex, unsigned SizeInBytes) { + assert(SizeInBytes <= sizeof(int64_t) && "Excessive size"); + return SizeInBytes | (PrintInHex ? PrintInHexBit : 0); + } MCConstantExpr(int64_t Value, bool PrintInHex, unsigned SizeInBytes) - : MCExpr(MCExpr::Constant, SMLoc()), Value(Value), PrintInHex(PrintInHex), - SizeInBytes(SizeInBytes) {} + : MCExpr(MCExpr::Constant, SMLoc(), + encodeSubclassData(PrintInHex, SizeInBytes)), Value(Value) {} public: /// \name Construction @@ -157,9 +171,11 @@ /// @{ int64_t getValue() const { return Value; } - unsigned getSizeInBytes() const { return SizeInBytes; } + unsigned getSizeInBytes() const { + return getSubclassData() & SizeInBytesMask; + } - bool useHexFormat() const { return PrintInHex; } + bool useHexFormat() const { return (getSubclassData() & PrintInHexBit) != 0; } /// @} @@ -315,17 +331,32 @@ }; private: - /// The symbol reference modifier. - const VariantKind Kind; + /// The symbol being referenced. + const MCSymbol *Symbol; + + // Subclass data stores VariantKind in bits 0..15, UseParensForSymbolVariant + // in bit 16 and HasSubsectionsViaSymbols in bit 17. + static const unsigned VariantKindBits = 16; + static const unsigned VariantKindMask = (1 << VariantKindBits) - 1; /// Specifies how the variant kind should be printed. - const unsigned UseParensForSymbolVariant : 1; + static const unsigned UseParensForSymbolVariantBit = 1 << VariantKindBits; // FIXME: Remove this bit. - const unsigned HasSubsectionsViaSymbols : 1; + static const unsigned HasSubsectionsViaSymbolsBit = + 1 << (VariantKindBits + 1); + + static unsigned encodeSubclassData(VariantKind Kind, + bool UseParensForSymbolVariant, + bool HasSubsectionsViaSymbols) { + return (unsigned)Kind | + (UseParensForSymbolVariant ? UseParensForSymbolVariantBit : 0) | + (HasSubsectionsViaSymbols ? HasSubsectionsViaSymbolsBit : 0); + } - /// The symbol being referenced. - const MCSymbol *Symbol; + bool useParensForSymbolVariant() const { + return (getSubclassData() & UseParensForSymbolVariantBit) != 0; + } explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, const MCAsmInfo *MAI, SMLoc Loc = SMLoc()); @@ -349,11 +380,15 @@ const MCSymbol &getSymbol() const { return *Symbol; } - VariantKind getKind() const { return Kind; } + VariantKind getKind() const { + return (VariantKind)(getSubclassData() & VariantKindMask); + } void printVariantKind(raw_ostream &OS) const; - bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } + bool hasSubsectionsViaSymbols() const { + return (getSubclassData() & HasSubsectionsViaSymbolsBit) != 0; + } /// @} /// \name Static Utility Functions @@ -381,11 +416,10 @@ }; private: - Opcode Op; const MCExpr *Expr; MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc) - : MCExpr(MCExpr::Unary, Loc), Op(Op), Expr(Expr) {} + : MCExpr(MCExpr::Unary, Loc, Op), Expr(Expr) {} public: /// \name Construction @@ -415,7 +449,7 @@ /// @{ /// Get the kind of this unary expression. - Opcode getOpcode() const { return Op; } + Opcode getOpcode() const { return (Opcode)getSubclassData(); } /// Get the child of this unary expression. const MCExpr *getSubExpr() const { return Expr; } @@ -457,12 +491,11 @@ }; 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) {} + : MCExpr(MCExpr::Binary, Loc, Op), LHS(LHS), RHS(RHS) {} public: /// \name Construction @@ -572,7 +605,7 @@ /// @{ /// Get the kind of this binary expression. - Opcode getOpcode() const { return Op; } + Opcode getOpcode() const { return (Opcode)getSubclassData(); } /// Get the left-hand side expression of the binary operator. const MCExpr *getLHS() const { return LHS; } diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -193,9 +193,9 @@ MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, const MCAsmInfo *MAI, SMLoc Loc) - : MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind), - UseParensForSymbolVariant(MAI->useParensForSymbolVariant()), - HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()), + : MCExpr(MCExpr::SymbolRef, Loc, + encodeSubclassData(Kind, MAI->useParensForSymbolVariant(), + MAI->hasSubsectionsViaSymbols())), Symbol(Symbol) { assert(Symbol); } @@ -464,7 +464,7 @@ } void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const { - if (UseParensForSymbolVariant) + if (useParensForSymbolVariant()) OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')'; else OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind());