source: src/AST/Type.hpp@ 4e13e2a

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 4e13e2a was 4eb43fa, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Merge branch 'new-ast' of plg.uwaterloo.ca:software/cfa/cfa-cc into new-ast

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