source: src/AST/Type.hpp@ f2898df

Last change on this file since f2898df was f5ec35a, checked in by Andrew Beach <ajbeach@…>, 23 months ago

Removed an extra forward declaration.

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