source: src/AST/Type.hpp@ 2377ca2

ADT ast-experimental enum pthread-emulation qualifiedEnum
Last change on this file since 2377ca2 was b238618, checked in by Andrew Beach <ajbeach@…>, 4 years ago

Added VTableType to the new ast.

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