Joos1W Compiler Framework
All Classes Functions Typedefs Pages
CGExpr.h
1 #pragma once
2 
3 #include "ast/AstNode.h"
4 #include "ast/ExprEvaluator.h"
5 #include "codegen/CodeGen.h"
6 #include "tir/Constant.h"
7 #include "tir/Context.h"
8 #include "tir/TIR.h"
9 
10 namespace codegen {
11 
12 namespace details {
13 
14 /**
15  * @brief Wraps a value for expression evaluation. This distinguishes an
16  * LValue from an RValue, wrapping the tir::Value* mapped from an ExprValue.
17  * The criteria for an L/R value is as follows:
18  * - Constants are wrapped R values always
19  * - Var and field decls are wrapped as L values always
20  * - Expressions are wrapped as R values always
21  * - Function decls are neither L nor R values
22  * The tir::Value can then be unwrapped using a conversion function.
23  */
24 class ValueWrapper {
25  struct TirWrapped {
26  ast::Type const* astType;
27  tir::Type* type;
28  tir::Value* value;
29  };
30 
31  struct FnWrapped {
32  ast::Decl const* decl;
33  tir::Value* refThis;
34  tir::Value* fn;
35  };
36 
37 public:
38  enum class Kind { StaticFn, MemberFn, AstType, AstDecl, L, R };
39 
40  /**
41  * @brief Wrap an AST Type node. This can not be an IR value.
42  *
43  * @param aty The AST type node to wrap.
44  */
45  explicit ValueWrapper(ast::Type const* aty)
46  : kind_{Kind::AstType}, data_{aty} {}
47 
48  /**
49  * @brief Wrap an AST FieldDecl node. This can not be an IR value.
50  *
51  * @param decl The AST field declaration node to wrap.
52  */
53  explicit ValueWrapper(ast::Decl const* decl)
54  : kind_{Kind::AstDecl}, data_{decl} {}
55 
56 private:
57  // Private constructor for wrapping IR values
58  explicit ValueWrapper(Kind kind, TirWrapped wrappedIr)
59  : kind_{kind}, data_{wrappedIr} {}
60  // Private constructor for wrapping function values
61  explicit ValueWrapper(Kind kind, FnWrapped wrappedFn)
62  : kind_{kind}, data_{wrappedFn} {}
63 
64 public:
65  /**
66  * @brief Create an L-value wrapper for a pointer value.
67  *
68  * @param aty The AST type of the reference.
69  * @param elemTy The dereferenced IR type.
70  * @param value The pointer value to wrap.
71  * @return ValueWrapper
72  */
73  static ValueWrapper L(ast::Type const* aty, tir::Type* elemTy,
74  tir::Value* value) {
75  return ValueWrapper{Kind::L, TirWrapped{aty, elemTy, value}};
76  }
77 
78  /**
79  * @brief Create an R-value wrapper for a non-pointer value.
80  *
81  * @param aty The AST type of the value.
82  * @param value The IR value to wrap.
83  * @return ValueWrapper The wrapped value.
84  */
85  static ValueWrapper R(ast::Type const* aty, tir::Value* value) {
86  assert(!value->type()->isPointerType() || isAstTypeReference(aty));
87  return ValueWrapper{Kind::R, TirWrapped{aty, value->type(), value}};
88  }
89 
90  /**
91  * @brief Wrap a static function value or a member function value.
92  *
93  * @param value The IR function value to wrap.
94  * @return ValueWrapper The wrapped value.
95  */
96  static ValueWrapper Fn(Kind kind, ast::Decl const* fn, tir::Value* value,
97  tir::Value* refThis = nullptr) {
98  assert(kind == Kind::StaticFn || kind == Kind::MemberFn);
99  return ValueWrapper{kind, FnWrapped{fn, refThis, value}};
100  }
101 
102  // Gets the wrapped IR value as an R-value
103  tir::Value* asRValue(tir::IRBuilder&) const;
104  // Gets the wrapped IR L-value
105  tir::Value* asLValue() const;
106  // Gets the wrapped IR value as a method/function
107  tir::Value* asFn() const;
108  // Gets the AST type of the IR value or the wrapped AST type
109  ast::Type const* astType() const;
110  // Gets the IR element type of the L-value or the type of the R-value
111  tir::Type* irType() const;
112  // Gets the kind of the wrapped value
113  Kind kind() const { return kind_; }
114  // Validates the wrapped value
115  bool validate(CodeGenerator& cg) const;
116  // Gets the wrapped AST declaration
117  ast::Decl const* asDecl() const;
118  // Get the thisRef
119  tir::Value* thisRef() const {
120  assert(kind_ == Kind::MemberFn);
121  return std::get<FnWrapped>(data_).refThis;
122  }
123  // Dump
124  void dump() const;
125 
126 private:
127  Kind kind_;
128  std::variant<TirWrapped, FnWrapped, ast::Type const*, ast::Decl const*> data_;
129 };
130 
131 } // namespace details
132 
133 /**
134  * @brief The code generator expression evaluator. This class is responsible
135  * for evaluating expressions and returning the corresponding tir::Value*.
136  */
137 class CGExprEvaluator final : public ast::ExprEvaluator<details::ValueWrapper> {
138 public:
139  using T = details::ValueWrapper;
140  explicit CGExprEvaluator(CodeGenerator& cg) : cg{cg} {}
141 
142 private:
143  T mapValue(ast::exprnode::ExprValue& node) const override;
144  T evalBinaryOp(ast::exprnode::BinaryOp& op, T lhs, T rhs) const override;
145  T evalUnaryOp(ast::exprnode::UnaryOp& op, T rhs) const override;
146  T evalMemberAccess(ast::exprnode::MemberAccess& op, T lhs,
147  T field) const override;
148  T evalMethodCall(ast::exprnode::MethodInvocation& op, T method,
149  const op_array& args) const override;
150  T evalNewObject(ast::exprnode::ClassInstanceCreation& op, T object,
151  const op_array& args) const override;
152  T evalNewArray(ast::exprnode::ArrayInstanceCreation& op, T type,
153  T size) const override;
154  T evalArrayAccess(ast::exprnode::ArrayAccess& op, T array,
155  T index) const override;
156  T evalCast(ast::exprnode::Cast& op, T type, T value) const override;
157  bool validate(T const& v) const override { return v.validate(cg); }
158  T castIntegerType(ast::Type const*, tir::Type*, T value) const;
159 
160 private:
161  CodeGenerator& cg;
162  tir::Context& ctx{cg.ctx};
163  tir::CompilationUnit& cu{cg.cu};
164  tir::Function& curFn{*cg.curFn};
165 };
166 
167 } // namespace codegen