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/IR/Function.h"
8 #include "llvm/IR/Instruction.h"
9 #include "llvm/IR/Instructions.h"
10 #include "llvm/IR/Module.h"
11 #include "llvm/Support/raw_ostream.h"
12 
13 #include "memoir/support/Assert.hpp"
14 #include "memoir/support/InternalDatatypes.hpp"
15 
16 #include "memoir/utility/FunctionNames.hpp"
17 
18 #include "memoir/ir/Instructions.hpp"
19 
20 namespace llvm::memoir {
21 
22 enum class TypeCode {
23  INTEGER,
24  FLOAT,
25  DOUBLE,
26  POINTER,
27  REFERENCE,
28  STRUCT,
29  FIELD_ARRAY,
30  STATIC_TENSOR,
31  TENSOR,
32  ASSOC_ARRAY,
33  SEQUENCE,
34  OTHER, // A special code for extensibility
35 };
36 
37 struct IntegerType;
38 struct FloatType;
39 struct DoubleType;
40 struct PointerType;
41 struct ReferenceType;
42 struct StructType;
43 struct FieldArrayType;
44 struct StaticTensorType;
45 struct TensorType;
46 struct AssocArrayType;
47 struct SequenceType;
48 
49 struct DefineStructTypeInst;
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 FloatType &get_f32_type();
65  static DoubleType &get_f64_type();
66  static PointerType &get_ptr_type();
67  static ReferenceType &get_ref_type(Type &referenced_type);
68  static StructType &define_struct_type(DefineStructTypeInst &definition,
69  std::string name,
70  vector<Type *> field_types);
71  static StructType &get_struct_type(std::string name);
72  static FieldArrayType &get_field_array_type(StructType &type,
73  unsigned field_index);
74  static StaticTensorType &get_static_tensor_type(
75  Type &element_type,
76  vector<size_t> dimension_lengths);
77  static TensorType &get_tensor_type(Type &element_type,
78  unsigned num_dimensions);
79  static AssocArrayType &get_assoc_array_type(Type &key_type, Type &value_type);
80  static SequenceType &get_sequence_type(Type &element_type);
81 
82  static bool is_primitive_type(Type &type);
83  static bool is_reference_type(Type &type);
84  static bool is_struct_type(Type &type);
85  static bool is_collection_type(Type &type);
86  static bool value_is_collection_type(llvm::Value &value);
87  static bool value_is_struct_type(llvm::Value &value);
88 
89  TypeCode getCode() const;
90 
91  // TODO: implement conversion to LLVM type
92  // virtual llvm::Type *getLLVMType() const;
93 
94  virtual std::string toString(std::string indent = "") const = 0;
95  virtual opt<std::string> get_code() const;
96 
97  friend std::ostream &operator<<(std::ostream &os, const Type &T);
98  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Type &T);
99  friend bool operator<(const Type &L, const Type &R);
100 
101  virtual ~Type() = default;
102 
103 protected:
104  TypeCode code;
105 
106  Type(TypeCode code);
107 
108  friend class TypeAnalysis;
109 };
110 
111 struct IntegerType : public Type {
112 public:
113  // Creation.
114  template <unsigned BW, bool S>
115  static IntegerType &get();
116 
117  // Access.
118  unsigned getBitWidth() const;
119  bool isSigned() const;
120 
121  // RTTI.
122  static bool classof(const Type *T) {
123  return (T->getCode() == TypeCode::INTEGER);
124  }
125 
126  // Debug.
127  std::string toString(std::string indent = "") const override;
128  opt<std::string> get_code() const override;
129 
130 protected:
131  unsigned bitwidth;
132  bool is_signed;
133 
134  IntegerType(unsigned bitwidth, bool is_signed);
135 
136  friend class TypeAnalysis;
137 };
138 
139 struct FloatType : public Type {
140 public:
141  static FloatType &get();
142 
143  static bool classof(const Type *T) {
144  return (T->getCode() == TypeCode::FLOAT);
145  }
146 
147  std::string toString(std::string indent = "") const override;
148  opt<std::string> get_code() const override;
149 
150 protected:
151  FloatType();
152 
153  friend class TypeAnalysis;
154 };
155 
156 struct DoubleType : public Type {
157 public:
158  static DoubleType &get();
159 
160  static bool classof(const Type *T) {
161  return (T->getCode() == TypeCode::DOUBLE);
162  }
163 
164  std::string toString(std::string indent = "") const override;
165  opt<std::string> get_code() const override;
166 
167 protected:
168  DoubleType();
169 
170  friend class TypeAnalysis;
171 };
172 
173 struct PointerType : public Type {
174 public:
175  static PointerType &get();
176 
177  static bool classof(const Type *T) {
178  return (T->getCode() == TypeCode::POINTER);
179  }
180 
181  std::string toString(std::string indent = "") const override;
182  opt<std::string> get_code() const override;
183 
184 protected:
185  PointerType();
186 
187  friend class TypeAnalysis;
188 };
189 
190 struct ReferenceType : public Type {
191 public:
192  static ReferenceType &get(Type &referenced_type);
193 
194  Type &getReferencedType() const;
195 
196  static bool classof(const Type *T) {
197  return (T->getCode() == TypeCode::REFERENCE);
198  }
199 
200  std::string toString(std::string indent = "") const override;
201  opt<std::string> get_code() const override;
202 
203 protected:
204  Type &referenced_type;
205 
206  static map<Type *, ReferenceType *> *reference_types;
207 
208  ReferenceType(Type &referenced_type);
209 
210  friend class TypeAnalysis;
211 };
212 
213 struct StructType : public Type {
214 public:
215  // Creation.
216  static StructType &define(DefineStructTypeInst &definition,
217  std::string name,
218  vector<Type *> field_types);
219  static StructType &get(std::string name);
220 
221  // Access.
222  DefineStructTypeInst &getDefinition() const;
223  std::string getName() const;
224  unsigned getNumFields() const;
225  Type &getFieldType(unsigned field_index) const;
226 
227  // RTTI.
228  static bool classof(const Type *T) {
229  return (T->getCode() == TypeCode::STRUCT);
230  }
231 
232  // Debug.
233  std::string toString(std::string indent = "") const override;
234  opt<std::string> get_code() const override;
235 
236 protected:
237  DefineStructTypeInst &definition;
238  std::string name;
239  vector<Type *> field_types;
240 
241  static map<std::string, StructType *> *defined_types;
242 
243  StructType(DefineStructTypeInst &definition,
244  std::string name,
245  vector<Type *> field_types);
246 
247  friend class TypeAnalysis;
248 };
249 
250 struct CollectionType : public Type {
251 public:
252  virtual Type &getElementType() const = 0;
253 
254  static bool classof(const Type *T) {
255  switch (T->getCode()) {
256  default:
257  return false;
258  case TypeCode::FIELD_ARRAY:
259  case TypeCode::STATIC_TENSOR:
260  case TypeCode::TENSOR:
261  case TypeCode::SEQUENCE:
262  case TypeCode::ASSOC_ARRAY:
263  return true;
264  };
265  }
266 
267  opt<std::string> get_code() const override;
268 
269 protected:
270  CollectionType(TypeCode code);
271 
272  friend class TypeAnalysis;
273 };
274 
276 public:
277  static FieldArrayType &get(StructType &struct_type, unsigned field_index);
278 
279  Type &getElementType() const override;
280 
281  StructType &getStructType() const;
282  unsigned getFieldIndex() const;
283 
284  static bool classof(const Type *T) {
285  return (T->getCode() == TypeCode::FIELD_ARRAY);
286  }
287 
288  std::string toString(std::string indent = "") const override;
289 
290 protected:
291  StructType &struct_type;
292  unsigned field_index;
293 
294  static map<StructType *, map<unsigned, FieldArrayType *>>
295  *struct_to_field_array;
296 
297  FieldArrayType(StructType &struct_type, unsigned field_index);
298 };
299 
301 public:
302  static StaticTensorType &get(Type &element_type,
303  vector<size_t> length_of_dimensions);
304 
305  Type &getElementType() const override;
306  unsigned getNumberOfDimensions() const;
307  size_t getLengthOfDimension(unsigned dimension_index) const;
308 
309  static bool classof(const Type *T) {
310  return (T->getCode() == TypeCode::STATIC_TENSOR);
311  }
312 
313  std::string toString(std::string indent = "") const override;
314 
315 protected:
316  Type &element_type;
317  unsigned number_of_dimensions;
318  vector<size_t> length_of_dimensions;
319 
320  StaticTensorType(Type &element_type,
321  unsigned number_of_dimensions,
322  vector<size_t> length_of_dimensions);
323 
324  static ordered_multimap<Type *, StaticTensorType *> *static_tensor_types;
325 
326  friend class TypeAnalysis;
327 };
328 
329 struct TensorType : public CollectionType {
330 public:
331  static TensorType &get(Type &element_type, unsigned num_dimensions);
332 
333  Type &getElementType() const override;
334  unsigned getNumberOfDimensions() const;
335 
336  static bool classof(const Type *T) {
337  return (T->getCode() == TypeCode::TENSOR);
338  }
339 
340  std::string toString(std::string indent = "") const override;
341 
342 protected:
343  Type &element_type;
344  unsigned number_of_dimensions;
345 
346  TensorType(Type &element_type, unsigned number_of_dimensions);
347 
348  static map<Type *, map<unsigned, TensorType *>> *tensor_types;
349 
350  friend class TypeAnalysis;
351 };
352 
354 public:
355  static AssocArrayType &get(Type &key_type, Type &value_type);
356 
357  Type &getKeyType() const;
358  Type &getValueType() const;
359  Type &getElementType() const override;
360 
361  static bool classof(const Type *T) {
362  return (T->getCode() == TypeCode::ASSOC_ARRAY);
363  }
364 
365  std::string toString(std::string indent = "") const override;
366 
367 protected:
368  Type &key_type;
369  Type &value_type;
370 
371  static map<Type *, map<Type *, AssocArrayType *>> *assoc_array_types;
372 
373  AssocArrayType(Type &key_type, Type &value_type);
374 
375  friend class TypeAnalysis;
376 };
377 
378 struct SequenceType : public CollectionType {
379 public:
380  static SequenceType &get(Type &element_type);
381 
382  Type &getElementType() const override;
383 
384  static bool classof(const Type *T) {
385  return (T->getCode() == TypeCode::SEQUENCE);
386  }
387 
388  std::string toString(std::string indent = "") const override;
389 
390 protected:
391  Type &element_type;
392 
393  static map<Type *, SequenceType *> *sequence_types;
394 
395  SequenceType(Type &element_type);
396 
397  friend class TypeAnalysis;
398 };
399 
406 Type *type_of(llvm::Value &V);
407 
408 struct MemOIRInst;
409 
416 Type *type_of(MemOIRInst &I);
417 
418 } // namespace llvm::memoir
419 
420 #endif
Definition: Types.hpp:111
Definition: Types.hpp:139
Definition: Types.hpp:300
Definition: Types.hpp:213
Definition: Types.hpp:378
Definition: Types.hpp:275
Definition: Instructions.hpp:334
Definition: Types.hpp:353
Definition: Types.hpp:190
Definition: Liveness.hpp:17
Definition: Instructions.hpp:31
Definition: Types.hpp:250
Definition: Types.hpp:173
Definition: Types.hpp:51
Definition: Types.hpp:156
Definition: Types.hpp:329