// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_MC_MCEXPR_H #define RCC_MC_MCEXPR_H #include "rcc/MC/MCSymbol.h" #include "rcc/Support/Error.h" #include #include #include #include #include namespace rcc::mc { class MCExpr; using MCExprRef = std::shared_ptr; enum class MCUnaryOperator : std::uint8_t { Plus, Minus, BitwiseNot, LogicalNot, }; enum class MCBinaryOperator : std::uint8_t { Add, Subtract, Multiply, Divide, Modulo, ShiftLeft, ShiftRight, BitwiseAnd, BitwiseOr, BitwiseXor, LogicalAnd, LogicalOr, Equal, NotEqual, Less, LessEqual, Greater, GreaterEqual, }; struct MCSymbolRefExpr final { MCSymbolRef Symbol; }; struct MCUnaryExpr final { MCUnaryOperator Operator = MCUnaryOperator::Plus; MCExprRef Operand; }; struct MCBinaryExpr final { MCBinaryOperator Operator = MCBinaryOperator::Add; MCExprRef Left; MCExprRef Right; }; struct MCTargetExpr final { std::uint32_t Kind = 0; MCExprRef Operand; }; class MCExpr final { public: enum class Kind : std::uint8_t { Constant, SymbolRef, Unary, Binary, Target, }; [[nodiscard]] static MCExprRef constant(std::int64_t Value); [[nodiscard]] static Expected symbol(MCSymbolRef Symbol); [[nodiscard]] static Expected unary(MCUnaryOperator Operator, MCExprRef Operand); [[nodiscard]] static Expected binary(MCBinaryOperator Operator, MCExprRef Left, MCExprRef Right); [[nodiscard]] static Expected target(std::uint32_t Kind, MCExprRef Operand); [[nodiscard]] Kind kind() const noexcept { return ExpressionKind; } template [[nodiscard]] const ValueT *getIf() const noexcept { return std::get_if(&Storage); } [[nodiscard]] Expected verify(std::size_t MaximumDepth = 256) const; [[nodiscard]] std::optional evaluateAbsolute() const noexcept; private: using StorageT = std::variant; MCExpr(Kind ExpressionKind, StorageT Storage) : ExpressionKind(ExpressionKind), Storage(std::move(Storage)) {} Kind ExpressionKind; StorageT Storage; }; } // namespace rcc::mc #endif // RCC_MC_MCEXPR_H