source: src/AST/Type.hpp@ 566cc33

Last change on this file since 566cc33 was fc1a3e2, checked in by Andrew Beach <ajbeach@…>, 17 months ago

Style update. Focused on indentation and trailing whitespace.

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