My Project
Types.hpp
1 #ifndef MEMOIR_IR_TYPES_H
2 #define MEMOIR_IR_TYPES_H
3 #pragma once
4 
5 #include <cstdio>
6 
7 #include "llvm/ADT/ArrayRef.h"
8 #include "llvm/IR/Function.h"
9 #include "llvm/IR/Instruction.h"
10 #include "llvm/IR/Instructions.h"
11 #include "llvm/IR/Module.h"
12 #include "llvm/Support/raw_ostream.h"
13 
14 #include "memoir/support/Assert.hpp"
15 #include "memoir/support/DataTypes.hpp"
16 
17 #include "memoir/utility/FunctionNames.hpp"
18 
19 #include "memoir/ir/Instructions.hpp"
20 
21 namespace llvm::memoir {
22 
23 enum class TypeKind {
24  INTEGER,
25  FLOAT,
26  DOUBLE,
27  POINTER,
28  VOID,
29  REFERENCE,
30  TUPLE,
31  ARRAY,
32  ASSOC_ARRAY,
33  SEQUENCE,
34  VARIABLE,
35  OTHER, // A special code for extensibility
36 };
37 
38 struct IntegerType;
39 struct FloatType;
40 struct DoubleType;
41 struct PointerType;
42 struct VoidType;
43 struct ReferenceType;
44 struct TupleType;
45 struct ArrayType;
46 struct AssocArrayType;
47 struct SequenceType;
48 
49 struct DefineTupleTypeInst;
50 
51 struct Type {
52 public:
53  static IntegerType &get_u64_type();
54  static IntegerType &get_u32_type();
55  static IntegerType &get_u16_type();
56  static IntegerType &get_u8_type();
57  static IntegerType &get_u2_type();
58  static IntegerType &get_i64_type();
59  static IntegerType &get_i32_type();
60  static IntegerType &get_i16_type();
61  static IntegerType &get_i8_type();
62  static IntegerType &get_i2_type();
63  static IntegerType &get_bool_type();
64  static IntegerType &get_size_type(const llvm::DataLayout &DL);
65  static FloatType &get_f32_type();
66  static DoubleType &get_f64_type();
67  static PointerType &get_ptr_type();
68  static VoidType &get_void_type();
69  static ReferenceType &get_ref_type(Type &referenced_type);
70  static Type &define_type(std::string name, Type &type);
71  static Type &lookup_type(std::string name);
72  static TupleType &get_tuple_type(llvm::ArrayRef<Type *> fields);
73  static ArrayType &get_array_type(Type &element_type, size_t length);
74 
75  static Type &from_code(std::string code);
76 
77  static bool is_primitive_type(Type &type);
78  static bool is_reference_type(Type &type);
79  static bool is_struct_type(Type &type);
80  static bool is_collection_type(Type &type);
81  static bool is_unsized(Type &type);
82  static bool value_is_object(llvm::Value &value);
83  static bool value_is_collection_type(llvm::Value &value);
84  static bool value_is_struct_type(llvm::Value &value);
85 
86  TypeKind getKind() const;
87 
88  // TODO: implement conversion to LLVM type
89  virtual llvm::Type *get_llvm_type(llvm::LLVMContext &C) const;
90 
91  virtual std::string toString(std::string indent = "") const = 0;
92  virtual Option<std::string> get_code() const;
93 
94  friend std::ostream &operator<<(std::ostream &os, const Type &T);
95  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Type &T);
96 
97  virtual bool operator==(const Type &other) const;
98  virtual bool operator<=(const Type &other) const;
99 
100  virtual ~Type() = default;
101 
102 protected:
103  TypeKind code;
104 
105  Type(TypeKind code);
106 };
107 
108 struct IntegerType : public Type {
109 public:
110  // Creation.
111  template <unsigned BW, bool S>
112  static IntegerType &get();
113 
114  // Access.
115  unsigned getBitWidth() const;
116  bool isSigned() const;
117 
118  // RTTI.
119  static bool classof(const Type *T) {
120  return (T->getKind() == TypeKind::INTEGER);
121  }
122 
123  // Debug.
124  std::string toString(std::string indent = "") const override;
125  Option<std::string> get_code() const override;
126 
127  llvm::Type *get_llvm_type(llvm::LLVMContext &C) const override;
128 
129 protected:
130  unsigned bitwidth;
131  bool is_signed;
132 
133  IntegerType(unsigned bitwidth, bool is_signed);
134 
135  friend struct Type;
136 };
137 
138 struct FloatType : public Type {
139 public:
140  static FloatType &get();
141 
142  static bool classof(const Type *T) {
143  return (T->getKind() == TypeKind::FLOAT);
144  }
145 
146  std::string toString(std::string indent = "") const override;
147  Option<std::string> get_code() const override;
148 
149  llvm::Type *get_llvm_type(llvm::LLVMContext &C) const override;
150 
151 protected:
152  FloatType();
153 };
154 
155 struct DoubleType : public Type {
156 public:
157  static DoubleType &get();
158 
159  static bool classof(const Type *T) {
160  return (T->getKind() == TypeKind::DOUBLE);
161  }
162 
163  std::string toString(std::string indent = "") const override;
164  Option<std::string> get_code() const override;
165 
166  llvm::Type *get_llvm_type(llvm::LLVMContext &C) const override;
167 
168 protected:
169  DoubleType();
170 };
171 
172 struct PointerType : public Type {
173 public:
174  static PointerType &get();
175 
176  static bool classof(const Type *T) {
177  return (T->getKind() == TypeKind::POINTER);
178  }
179 
180  std::string toString(std::string indent = "") const override;
181  Option<std::string> get_code() const override;
182 
183  llvm::Type *get_llvm_type(llvm::LLVMContext &C) const override;
184 
185 protected:
186  PointerType();
187 };
188 
189 struct VoidType : public Type {
190 public:
191  static VoidType &get();
192 
193  static bool classof(const Type *T) {
194  return (T->getKind() == TypeKind::VOID);
195  }
196 
197  std::string toString(std::string indent = "") const override;
198  Option<std::string> get_code() const override;
199 
200  llvm::Type *get_llvm_type(llvm::LLVMContext &C) const override;
201 
202 protected:
203  VoidType();
204 };
205 
206 struct ReferenceType : public Type {
207 public:
208  static ReferenceType &get(Type &referenced_type);
209 
210  Type &getReferencedType() const;
211 
212  static bool classof(const Type *T) {
213  return (T->getKind() == TypeKind::REFERENCE);
214  }
215 
216  std::string toString(std::string indent = "") const override;
217  Option<std::string> get_code() const override;
218 
219  llvm::Type *get_llvm_type(llvm::LLVMContext &C) const override;
220 
221 protected:
222  Type &referenced_type;
223 
224  static Map<Type *, ReferenceType *> *reference_types;
225 
226  ReferenceType(Type &referenced_type);
227 };
228 
229 struct ObjectType : public Type {
230 public:
231  static bool classof(const Type *T) {
232  switch (T->getKind()) {
233  default:
234  return false;
235  case TypeKind::TUPLE:
236  case TypeKind::ARRAY:
237  case TypeKind::SEQUENCE:
238  case TypeKind::ASSOC_ARRAY:
239  return true;
240  };
241  }
242 
243 protected:
244  ObjectType(TypeKind code);
245 };
246 
247 struct TupleType : public ObjectType {
248 public:
249  // Creation.
250  static TupleType &get(llvm::ArrayRef<Type *> field_types);
251 
252  // Access.
253  unsigned getNumFields() const;
254  Type &getFieldType(unsigned field) const;
255  llvm::ArrayRef<Type *> fields() const;
256 
257  llvm::Type *get_llvm_type(llvm::LLVMContext &C) const override;
258 
259  // RTTI.
260  static bool classof(const Type *T) {
261  return (T->getKind() == TypeKind::TUPLE);
262  }
263 
264  // Debug.
265  std::string toString(std::string indent = "") const override;
266  Option<std::string> get_code() const override;
267 
268 protected:
269  Vector<Type *> field_types;
270 
271  static OrderedMultiMap<unsigned, TupleType *> *tuple_types;
272 
273  TupleType(llvm::ArrayRef<Type *> fields);
274 };
275 
276 struct CollectionType : public ObjectType {
277 public:
278  virtual Type &getElementType() const = 0;
279 
280  static bool classof(const Type *T) {
281  switch (T->getKind()) {
282  default:
283  return false;
284  case TypeKind::ARRAY:
285  case TypeKind::SEQUENCE:
286  case TypeKind::ASSOC_ARRAY:
287  return true;
288  };
289  }
290 
291  Option<std::string> get_code() const override;
292 
293  virtual Option<std::string> get_selection() const;
294  virtual CollectionType &set_selection(Option<std::string> selection);
295 
296  llvm::Type *get_llvm_type(llvm::LLVMContext &C) const override;
297 
298 protected:
299  CollectionType(TypeKind code);
300 };
301 
302 struct ArrayType : public CollectionType {
303 public:
304  static ArrayType &get(Type &element_type, size_t length);
305 
306  Type &getElementType() const override;
307  size_t getLength() const;
308 
309  static bool classof(const Type *T) {
310  return (T->getKind() == TypeKind::ARRAY);
311  }
312 
313  std::string toString(std::string indent = "") const override;
314 
315 protected:
316  Type &element_type;
317  size_t length;
318 
319  ArrayType(Type &element_type, size_t length);
320 
321  static OrderedMultiMap<Type *, ArrayType *> *array_types;
322 };
323 
325 public:
326  static AssocArrayType &get(Type &key_type,
327  Type &value_type,
328  std::optional<std::string> selection = {});
329 
330  Type &getKeyType() const;
331  Type &getValueType() const;
332  Type &getElementType() const override;
333 
334  Option<std::string> get_selection() const override;
335  CollectionType &set_selection(Option<std::string> selection) override;
336 
337  static bool classof(const Type *T) {
338  return (T->getKind() == TypeKind::ASSOC_ARRAY);
339  }
340 
341  std::string toString(std::string indent = "") const override;
342 
343  Option<std::string> get_code() const override;
344 
345  bool operator<=(const Type &other) const override;
346 
347 protected:
348  Type &key_type;
349  Type &value_type;
350  Option<std::string> selection;
351 
352  typedef OrderedMap<
353  Type *,
354  OrderedMap<Type *,
355  OrderedMap<std::optional<std::string>, AssocArrayType *>>>
356  Types;
357  static Types *assoc_array_types;
358 
359  AssocArrayType(Type &key_type,
360  Type &value_type,
361  Option<std::string> selection = {});
362 };
363 using AssocType = struct AssocArrayType;
364 
365 struct SequenceType : public CollectionType {
366 public:
367  static SequenceType &get(Type &element_type,
368  std::optional<std::string> selection = {});
369 
370  Type &getElementType() const override;
371 
372  static bool classof(const Type *T) {
373  return (T->getKind() == TypeKind::SEQUENCE);
374  }
375 
376  std::string toString(std::string indent = "") const override;
377 
378  Option<std::string> get_code() const override;
379 
380  Option<std::string> get_selection() const override;
381  CollectionType &set_selection(Option<std::string> selection) override;
382 
383  bool operator<=(const Type &other) const override;
384 
385 protected:
386  Type &element_type;
387  Option<std::string> selection;
388 
389  typedef OrderedMap<Type *,
390  OrderedMap<std::optional<std::string>, SequenceType *>>
391  Types;
392  static Types *sequence_types;
393 
394  SequenceType(Type &element_type, Option<std::string> selection = {});
395 };
396 
400 struct TypeVariable : public Type {
401 public:
402  using TypeID = uint64_t;
403 
404  static TypeVariable &get() {
405  static TypeID id = 0;
406  auto *var = new TypeVariable(id++);
407  return *var;
408  }
409 
410  // Equality.
411  bool operator==(Type &T) const {
412  if (auto *tvar = dyn_cast<TypeVariable>(&T)) {
413  return tvar->id == this->id;
414  }
415  return false;
416  }
417 
418  // This class will only be used in the context of the base types and
419  // itself, so it is the only one that follows "other".
420  static bool classof(const Type *t) {
421  return (t->getKind() == TypeKind::VARIABLE);
422  }
423 
424  std::string toString(std::string indent = "") const override {
425  return "typevar(" + std::to_string(this->id) + ")";
426  }
427 
428 protected:
429  TypeVariable(TypeID id) : Type(TypeKind::VARIABLE), id(id) {}
430 
431  TypeID id;
432 };
433 
440 Type *type_of(llvm::Value &V);
441 
442 struct MemOIRInst;
443 
450 Type *type_of(MemOIRInst &I);
451 
452 } // namespace llvm::memoir
453 
454 #endif
Definition: Types.hpp:302
Definition: Types.hpp:324
Definition: Types.hpp:276
Definition: Types.hpp:155
Definition: Types.hpp:138
Definition: Types.hpp:108
Definition: Instructions.hpp:31
Definition: Types.hpp:229
Definition: Types.hpp:172
Definition: Types.hpp:206
Definition: Types.hpp:365
Definition: Types.hpp:247
Definition: Types.hpp:400
Definition: Types.hpp:51
Definition: Types.hpp:189