Joos1W Compiler Framework
All Classes Functions Typedefs Pages
Value.h
1 #pragma once
2 
3 #include <utils/Assert.h>
4 
5 #include <optional>
6 #include <ostream>
7 #include <ranges>
8 #include <string_view>
9 #include <unordered_set>
10 
11 #include "tir/Context.h"
12 
13 namespace tir {
14 
15 class User;
16 
17 /**
18  * @brief
19  */
20 class Value {
21 public:
22  Value(Context& ctx, Type* type)
23  : ctx_{ctx},
24  type_{type},
25  users_{ctx.alloc()},
26  name_{std::nullopt},
27  valueID_{ctx.getNextValueID()} {}
28  tir::Context& ctx() { return ctx_; }
29  auto users() { return std::views::all(users_); }
30  auto users() const { return std::views::all(users_); }
31  Type* type() const { return type_; }
32  void addUser(User* user) { users_.insert(user); }
33  void removeUser(User* user) { users_.erase(user); }
34  std::string_view name() const { return name_.value(); }
35  auto nameOpt() const { return name_.value(); }
36  void replaceAllUsesWith(Value* newValue);
37  void setName(std::string_view name) {
38  name_ = std::pmr::string{name, ctx_.alloc()};
39  }
40  std::ostream& printName(std::ostream& os) const {
41  os << "%";
42  if(name_) os << name_.value() << ".";
43  os << valueID_;
44  return os;
45  }
46  virtual std::ostream& print(std::ostream&) const = 0;
47  void dump() const;
48  virtual ~Value() = default;
49 
50 private:
51  tir::Context& ctx_;
52  tir::Type* const type_;
53  std::pmr::unordered_set<User*> users_;
54  std::optional<std::pmr::string> name_;
55  unsigned valueID_;
56 };
57 
58 /**
59  * @brief
60  */
61 class User : public Value {
62  friend class Value;
63 public:
64  User(Context& ctx, Type* type) : Value{ctx, type}, children_{ctx.alloc()} {}
65  auto children() const { return std::views::all(children_); }
66  auto numChildren() const { return children_.size(); }
67  Value* getChild(unsigned idx) const {
68  assert(idx < numChildren() && "Index out of bounds");
69  return children_[idx];
70  }
71 
72 protected:
73  void addChild(Value* operand) {
74  children_.push_back(operand);
75  operand->addUser(this);
76  }
77  void replaceChild(unsigned idx, Value* operand) {
78  assert(idx < numChildren() && "Index out of bounds");
79  children_[idx]->removeUser(this);
80  children_[idx] = operand;
81  operand->addUser(this);
82  }
83  void destroy() {
84  assert(!destroyed_);
85  for(auto child : children_) {
86  child->removeUser(this);
87  }
88  }
89  bool isDestroyed() const { return destroyed_; }
90 
91 private:
92  std::pmr::vector<Value*> children_;
93  bool destroyed_ = false;
94 };
95 
96 std::ostream& operator<<(std::ostream& os, const Value& val);
97 
98 } // namespace tir