source: src/AST/Type.hpp@ 81da70a5

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 81da70a5 was 7030dab, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Merge branch 'master' into new-ast

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