source: src/AST/Type.hpp@ 9802f4c

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 9802f4c was 3f3bfe5a, checked in by Andrew Beach <ajbeach@…>, 6 years ago

Merge from master to new-ast. Removing old lvalue support.

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