source: src/AST/Type.hpp@ 006d4c4

Last change on this file since 006d4c4 was acb33f15, checked in by JiadaL <j82liang@…>, 16 months ago

Change enum conversion steps

  • Property mode set to 100644
File size: 16.8 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Type.hpp --
8//
9// Author : Aaron B. Moss
10// Created On : Thu May 9 10:00:00 2019
11// Last Modified By : Andrew Beach
12// Last Modified On : Thu Apr 6 15:58:00 2023
13// Update Count : 9
14//
15
16#pragma once
17
18#include <cassert>
19#include <cstddef> // for nullptr_t
20#include <cstdint> // for uintptr_t
21#include <utility> // for move
22#include <vector>
23
24#include "BasicKind.hpp" // for BasicKind
25#include "CVQualifiers.hpp"
26#include "Decl.hpp" // for AggregateDecl subclasses
27#include "Fwd.hpp"
28#include "Node.hpp" // for Node, ptr, ptr_base
29#include "Visitor.hpp"
30
31// Must be included in *all* AST classes; should be #undef'd at the end of the file
32#define MUTATE_FRIEND \
33 template<typename node_t> friend node_t * mutate(const node_t * node); \
34 template<typename node_t> friend node_t * shallowCopy(const node_t * node);
35
36namespace ast {
37
38class Type : public Node {
39public:
40 CV::Qualifiers qualifiers;
41 std::vector<ptr<Attribute>> attributes;
42
43 Type( CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
44 : qualifiers(q), attributes(std::move(as)) {}
45
46 bool is_const() const { return qualifiers.is_const; }
47 bool is_volatile() const { return qualifiers.is_volatile; }
48 bool is_restrict() const { return qualifiers.is_restrict; }
49 bool is_mutex() const { return qualifiers.is_mutex; }
50 bool is_atomic() const { return qualifiers.is_atomic; }
51
52 Type * set_const( bool v ) { qualifiers.is_const = v; return this; }
53 Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
54 Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
55 Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
56 Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
57
58 /// How many elemental types are represented by this type
59 virtual unsigned size() const { return 1; }
60 /// Is this a void type?
61 virtual bool isVoid() const { return size() == 0; }
62 /// Get the i'th component of this type
63 virtual const Type * getComponent( unsigned i ) const;
64
65 /// type without outer pointers and arrays
66 const Type * stripDeclarator() const;
67 /// type without outer references
68 const Type * stripReferences() const;
69 /// number of reference occuring consecutively on the outermost layer of this type
70 /// (i.e. do not count references nested within other types)
71 virtual unsigned referenceDepth() const { return 0; }
72 /// true iff type is complete type (i.e. compiler knows the size, alignment, and layout)
73 virtual bool isComplete() const { return true; }
74
75 virtual const Type * accept( Visitor & v ) const override = 0;
76private:
77 virtual Type * clone() const override = 0;
78 MUTATE_FRIEND
79};
80
81/// Clear/reset the qualifiers on this type, cloning only if necessary
82template< enum Node::ref_type ref_t >
83void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) {
84 if ( p->qualifiers != q ) p.get_and_mutate()->qualifiers = q;
85}
86
87/// Add the specified qualifiers to this type, cloning only if necessary
88template< enum Node::ref_type ref_t >
89void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
90 if ( ( p->qualifiers & q ) != q ) p.get_and_mutate()->qualifiers |= q;
91}
92
93/// Remove the specified qualifiers from this type, cloning only if necessary
94template< enum Node::ref_type ref_t >
95void remove_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
96 if ( ( p->qualifiers & q ) != 0 ) p.get_and_mutate()->qualifiers -= q;
97}
98
99/// `void`
100class VoidType final : public Type {
101public:
102 VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
103
104 unsigned size() const override { return 0; }
105 bool isVoid() const override { return true; }
106 bool isComplete() const override { return false; }
107
108 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
109private:
110 VoidType * clone() const override { return new VoidType{ *this }; }
111 MUTATE_FRIEND
112};
113
114/// Built-in arithmetic type
115class BasicType final : public Type {
116public:
117 BasicKind kind;
118
119 /// string names of basic types; generated to match with Kind
120 static const char *typeNames[];
121
122 BasicType( BasicKind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
123 : Type(q, std::move(as)), kind(k) {}
124
125 /// Check if this type represents an integer type
126 bool isInteger() const { return kind <= MAX_INTEGER_TYPE; }
127
128 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
129private:
130 BasicType * clone() const override { return new BasicType{ *this }; }
131 MUTATE_FRIEND
132};
133
134/// Pointer/array variable length?
135enum LengthFlag { FixedLen, VariableLen };
136
137/// Pointer/array static dimension?
138enum DimensionFlag { DynamicDim, StaticDim };
139
140/// Pointer type `T*`
141class PointerType final : public Type {
142public:
143 ptr<Type> base;
144
145 // In C99, pointer types can be qualified in many ways, e.g. `int a[ static 3 ]`
146 ptr<Expr> dimension;
147 LengthFlag isVarLen = FixedLen;
148 DimensionFlag isStatic = DynamicDim;
149
150 PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
151 PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
152 CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
153
154 // true if this pointer is actually an array
155 bool isArray() const { return isVarLen || isStatic || dimension; }
156
157 bool isComplete() const override { return ! isVarLen; }
158
159 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
160private:
161 PointerType * clone() const override { return new PointerType{ *this }; }
162 MUTATE_FRIEND
163};
164
165/// Array type `T[]`
166class ArrayType final : public Type {
167public:
168 ptr<Type> base;
169 ptr<Expr> dimension;
170 LengthFlag isVarLen;
171 DimensionFlag isStatic;
172
173 ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
174 CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
175
176 // array types are complete if they have a dimension expression or are
177 // VLAs ('*' in parameter declaration), and incomplete otherwise.
178 // See 6.7.6.2
179 bool isComplete() const override { return dimension || isVarLen; }
180
181 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
182private:
183 ArrayType * clone() const override { return new ArrayType{ *this }; }
184 MUTATE_FRIEND
185};
186
187/// Reference type `T&`
188class ReferenceType final : public Type {
189public:
190 ptr<Type> base;
191
192 ReferenceType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
193
194 unsigned referenceDepth() const override { return base->referenceDepth() + 1; }
195
196 // Since reference types act like value types, their size is the size of the base.
197 // This makes it simple to cast the empty tuple to a reference type, since casts that increase
198 // the number of values are disallowed.
199 unsigned size() const override { return base->size(); }
200
201 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
202private:
203 ReferenceType * clone() const override { return new ReferenceType{ *this }; }
204 MUTATE_FRIEND
205};
206
207/// Qualified type `P.C`
208class QualifiedType final : public Type {
209public:
210 ptr<Type> parent;
211 ptr<Type> child;
212
213 QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
214 : Type(q), parent(p), child(c) {}
215
216 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
217private:
218 QualifiedType * clone() const override { return new QualifiedType{ *this }; }
219 MUTATE_FRIEND
220};
221
222/// Type of a function `[R1, R2](*)(P1, P2, P3)`
223class FunctionType final : public Type {
224public:
225 using ForallList = std::vector<ptr<TypeInstType>>;
226 using AssertionList = std::vector<ptr<VariableExpr>>;
227 ForallList forall;
228 AssertionList assertions;
229
230 std::vector<ptr<Type>> returns;
231 std::vector<ptr<Type>> params;
232
233 /// Does the function accept a variable number of arguments following the arguments specified
234 /// in the parameters list.
235 /// This could be because of
236 /// - an ellipsis in a prototype declaration
237 /// - an unprototyped declaration
238 ArgumentFlag isVarArgs;
239
240 FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
241 : Type(q), returns(), params(), isVarArgs(va) {}
242
243 FunctionType( const FunctionType & o ) = default;
244
245 /// true if either the parameters or return values contain a tttype
246 bool isTtype() const;
247 /// true if function parameters are unconstrained by prototype
248 bool isUnprototyped() const { return isVarArgs && params.size() == 0; }
249
250 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
251private:
252 FunctionType * clone() const override { return new FunctionType{ *this }; }
253 MUTATE_FRIEND
254};
255
256/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
257class BaseInstType : public Type {
258public:
259 std::vector<ptr<Expr>> params;
260 std::string name;
261 bool hoistType = false;
262
263 BaseInstType(
264 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
265 : Type(q, std::move(as)), params(), name(n) {}
266
267 BaseInstType(
268 const std::string& n, std::vector<ptr<Expr>> && params,
269 CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
270 : Type(q, std::move(as)), params(std::move(params)), name(n) {}
271
272 BaseInstType( const BaseInstType & o ) = default;
273
274 /// Gets aggregate declaration this type refers to
275 virtual const AggregateDecl * aggr() const = 0;
276 /// Looks up member declarations with given name
277 std::vector<readonly<Decl>> lookup( const std::string & name ) const;
278
279private:
280 virtual BaseInstType * clone() const override = 0;
281 MUTATE_FRIEND
282};
283
284// Common implementation for the SUE instance types. Not to be used directly.
285template<typename decl_t>
286class SueInstType final : public BaseInstType {
287public:
288 using base_type = decl_t;
289 readonly<decl_t> base;
290
291 SueInstType(
292 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
293 : BaseInstType( n, q, std::move(as) ), base() {}
294
295 SueInstType(
296 const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
297
298 SueInstType(
299 const base_type * b, std::vector<ptr<Expr>> && params,
300 CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
301
302 bool isComplete() const override;
303
304 const decl_t * aggr() const override { return base; }
305
306 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
307private:
308 SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; }
309 MUTATE_FRIEND
310};
311
312/// An instance of a struct type.
313using StructInstType = SueInstType<StructDecl>;
314
315/// An instance of a union type.
316using UnionInstType = SueInstType<UnionDecl>;
317
318/// An instance of an enum type.
319using EnumInstType = SueInstType<EnumDecl>;
320
321/// An instance of a trait type.
322class TraitInstType final : public BaseInstType {
323public:
324 readonly<TraitDecl> base;
325
326 TraitInstType(
327 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
328 : BaseInstType( n, q, std::move(as) ), base() {}
329
330 TraitInstType(
331 const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
332
333 // not meaningful for TraitInstType
334 bool isComplete() const override { assert(false); }
335
336 const TraitDecl * aggr() const override { return base; }
337
338 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
339private:
340 TraitInstType * clone() const override { return new TraitInstType{ *this }; }
341 MUTATE_FRIEND
342};
343
344struct TypeEnvKey;
345
346/// instance of named type alias (typedef or variable)
347class TypeInstType final : public BaseInstType {
348public:
349 readonly<TypeDecl> base;
350 // previously from renameTyVars; now directly use integer fields instead of synthesized strings
351 // a nonzero value of formal_usage indicates a formal type (only used in function type)
352 // a zero value of formal_usage indicates an actual type (referenced inside body of parametric structs and functions)
353 TypeDecl::Kind kind;
354 int formal_usage = 0;
355 int expr_id = 0;
356
357 bool operator==(const TypeInstType & other) const;
358
359 TypeInstType(
360 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
361 std::vector<ptr<Attribute>> && as = {} )
362 : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
363
364 TypeInstType( const TypeDecl * b,
365 CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
366
367 TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
368 std::vector<ptr<Attribute>> && as = {} )
369 : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
370
371 TypeInstType( const TypeInstType & o ) = default;
372
373 explicit TypeInstType( const TypeEnvKey & key );
374
375 /// sets `base`, updating `kind` correctly
376 void set_base( const TypeDecl * );
377
378 bool isComplete() const override;
379
380 // not meaningful for TypeInstType
381 const AggregateDecl * aggr() const override { assert(false); }
382
383 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
384
385 std::string typeString() const {
386 if (formal_usage > 0) return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + name;
387 else return name;
388 }
389private:
390 TypeInstType * clone() const override { return new TypeInstType{ *this }; }
391 MUTATE_FRIEND
392};
393
394/// Compact representation of TypeInstType used for map lookups.
395struct TypeEnvKey {
396 const TypeDecl * base = nullptr;
397 int formal_usage = 0;
398 int expr_id = 0;
399
400 TypeEnvKey() = default;
401 TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0)
402 : base(base), formal_usage(formal_usage), expr_id(expr_id) {}
403 TypeEnvKey(const TypeInstType & inst)
404 : base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
405 std::string typeString() const;
406 bool operator==(const TypeEnvKey & other) const;
407 bool operator<(const TypeEnvKey & other) const;
408 operator bool() {return base;}
409};
410
411
412/// tuple type e.g. `[int, char]`
413class TupleType final : public Type {
414public:
415 std::vector<ptr<Type>> types;
416
417 TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
418
419 // collection simulation
420 using iterator = std::vector<ptr<Type>>::const_iterator;
421 iterator begin() const { return types.begin(); }
422 iterator end() const { return types.end(); }
423
424 unsigned size() const override { return types.size(); }
425
426 const Type * getComponent( unsigned i ) const override {
427 assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
428 i, size() );
429 return *(begin()+i);
430 }
431
432 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
433private:
434 TupleType * clone() const override { return new TupleType{ *this }; }
435 MUTATE_FRIEND
436};
437
438/// Type of unresolved `typeof()` expression
439class TypeofType : public Type {
440public:
441 ptr<Expr> expr;
442 enum Kind { Typeof, Basetypeof } kind;
443
444 TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
445 : Type(q), expr(e), kind(k) {}
446
447 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
448private:
449 TypeofType * clone() const override { return new TypeofType{ *this }; }
450 MUTATE_FRIEND
451};
452
453/// Virtual Table Type `vtable(T)`
454class VTableType final : public Type {
455public:
456 ptr<Type> base;
457
458 VTableType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
459
460 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
461private:
462 VTableType * clone() const override { return new VTableType{ *this }; }
463 MUTATE_FRIEND
464};
465
466/// GCC built-in varargs type
467class VarArgsType final : public Type {
468public:
469 VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
470
471 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
472private:
473 VarArgsType * clone() const override { return new VarArgsType{ *this }; }
474 MUTATE_FRIEND
475};
476
477/// Type of zero constant `0`
478class ZeroType final : public Type {
479public:
480 ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
481
482 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
483private:
484 ZeroType * clone() const override { return new ZeroType{ *this }; }
485 MUTATE_FRIEND
486};
487
488/// Type of one constant `1`
489class OneType final : public Type {
490public:
491 OneType( CV::Qualifiers q = {} ) : Type( q ) {}
492
493 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
494private:
495 OneType * clone() const override { return new OneType{ *this }; }
496 MUTATE_FRIEND
497};
498
499/// Parent type for scope-qualified types at global scope
500class GlobalScopeType final : public Type {
501public:
502 GlobalScopeType() : Type() {}
503
504 const Type * accept( Visitor & v ) const override { return v.visit( this ); }
505private:
506 GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
507 MUTATE_FRIEND
508};
509
510bool isUnboundType(const Type * type);
511
512}
513
514namespace std {
515 template<>
516 struct hash<typename ast::TypeEnvKey> {
517 size_t operator() (const ast::TypeEnvKey & x) const {
518 const size_t p = 1000007;
519 size_t res = reinterpret_cast<size_t>(x.base);
520 res = p * res + x.formal_usage;
521 res = p * res + x.expr_id;
522 return res;
523 }
524 };
525}
526
527#undef MUTATE_FRIEND
528
529// Local Variables: //
530// tab-width: 4 //
531// mode: c++ //
532// compile-command: "make install" //
533// End: //
Note: See TracBrowser for help on using the repository browser.