aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/MC/MCExpr.h
blob: 15ff6fde89191ac07009c74de922d81032eb5782 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// 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 <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <variant>

namespace rcc::mc {

class MCExpr;
using MCExprRef = std::shared_ptr<const MCExpr>;

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<MCExprRef> symbol(MCSymbolRef Symbol);
  [[nodiscard]] static Expected<MCExprRef> unary(MCUnaryOperator Operator, MCExprRef Operand);
  [[nodiscard]] static Expected<MCExprRef> binary(MCBinaryOperator Operator, MCExprRef Left,
                                                  MCExprRef Right);
  [[nodiscard]] static Expected<MCExprRef> target(std::uint32_t Kind, MCExprRef Operand);

  [[nodiscard]] Kind kind() const noexcept {
    return ExpressionKind;
  }

  template <typename ValueT> [[nodiscard]] const ValueT *getIf() const noexcept {
    return std::get_if<ValueT>(&Storage);
  }

  [[nodiscard]] Expected<void> verify(std::size_t MaximumDepth = 256) const;
  [[nodiscard]] std::optional<std::int64_t> evaluateAbsolute() const noexcept;

private:
  using StorageT =
      std::variant<std::int64_t, MCSymbolRefExpr, MCUnaryExpr, MCBinaryExpr, MCTargetExpr>;

  MCExpr(Kind ExpressionKind, StorageT Storage)
      : ExpressionKind(ExpressionKind), Storage(std::move(Storage)) {}

  Kind ExpressionKind;
  StorageT Storage;
};

} // namespace rcc::mc

#endif // RCC_MC_MCEXPR_H