source: src/AST/Type.hpp @ 6740533e

Last change on this file since 6740533e was acb33f15, checked in by JiadaL <j82liang@…>, 6 months ago

Change enum conversion steps

  • Property mode set to 100644
File size: 16.8 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
321/// An instance of a trait type.
322class TraitInstType final : public BaseInstType {
323public:
324        readonly<TraitDecl> base;
325
326        TraitInstType(
327                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
328        : BaseInstType( n, q, std::move(as) ), base() {}
329
330        TraitInstType(
331                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
332
333        // not meaningful for TraitInstType
334        bool isComplete() const override { assert(false); }
335
336        const TraitDecl * aggr() const override { return base; }
337
338        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
339private:
340        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
341        MUTATE_FRIEND
342};
343
344struct TypeEnvKey;
345
346/// instance of named type alias (typedef or variable)
347class TypeInstType final : public BaseInstType {
348public:
349        readonly<TypeDecl> base;
350        // previously from renameTyVars; now directly use integer fields instead of synthesized strings
351        // a nonzero value of formal_usage indicates a formal type (only used in function type)
352        // a zero value of formal_usage indicates an actual type (referenced inside body of parametric structs and functions)
353        TypeDecl::Kind kind;
354        int formal_usage = 0;
355        int expr_id = 0;
356
357        bool operator==(const TypeInstType & other) const;
358
359        TypeInstType(
360                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
361                std::vector<ptr<Attribute>> && as = {} )
362        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
363
364        TypeInstType( const TypeDecl * b,
365                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
366
367        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
368                std::vector<ptr<Attribute>> && as = {} )
369        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
370
371        TypeInstType( const TypeInstType & o ) = default;
372
373        explicit TypeInstType( const TypeEnvKey & key );
374
375        /// sets `base`, updating `kind` correctly
376        void set_base( const TypeDecl * );
377
378        bool isComplete() const override;
379
380        // not meaningful for TypeInstType
381        const AggregateDecl * aggr() const override { assert(false); }
382
383        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
384
385        std::string typeString() const {
386                if (formal_usage > 0) return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + name;
387                else return name;
388        }
389private:
390        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
391        MUTATE_FRIEND
392};
393
394/// Compact representation of TypeInstType used for map lookups.
395struct TypeEnvKey {
396        const TypeDecl * base = nullptr;
397        int formal_usage = 0;
398        int expr_id = 0;
399
400        TypeEnvKey() = default;
401        TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0)
402        : base(base), formal_usage(formal_usage), expr_id(expr_id) {}
403        TypeEnvKey(const TypeInstType & inst)
404        : base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
405        std::string typeString() const;
406        bool operator==(const TypeEnvKey & other) const;
407        bool operator<(const TypeEnvKey & other) const;
408        operator bool() {return base;}
409};
410
411
412/// tuple type e.g. `[int, char]`
413class TupleType final : public Type {
414public:
415        std::vector<ptr<Type>> types;
416
417        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
418
419        // collection simulation
420        using iterator = std::vector<ptr<Type>>::const_iterator;
421        iterator begin() const { return types.begin(); }
422        iterator end() const { return types.end(); }
423
424        unsigned size() const override { return types.size(); }
425
426        const Type * getComponent( unsigned i ) const override {
427                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
428                        i, size() );
429                return *(begin()+i);
430        }
431
432        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
433private:
434        TupleType * clone() const override { return new TupleType{ *this }; }
435        MUTATE_FRIEND
436};
437
438/// Type of unresolved `typeof()` expression
439class TypeofType : public Type {
440public:
441        ptr<Expr> expr;
442        enum Kind { Typeof, Basetypeof } kind;
443
444        TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
445        : Type(q), expr(e), kind(k) {}
446
447        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
448private:
449        TypeofType * clone() const override { return new TypeofType{ *this }; }
450        MUTATE_FRIEND
451};
452
453/// Virtual Table Type `vtable(T)`
454class VTableType final : public Type {
455public:
456        ptr<Type> base;
457
458        VTableType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
459
460        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
461private:
462        VTableType * clone() const override { return new VTableType{ *this }; }
463        MUTATE_FRIEND
464};
465
466/// GCC built-in varargs type
467class VarArgsType final : public Type {
468public:
469        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
470
471        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
472private:
473        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
474        MUTATE_FRIEND
475};
476
477/// Type of zero constant `0`
478class ZeroType final : public Type {
479public:
480        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
481
482        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
483private:
484        ZeroType * clone() const override { return new ZeroType{ *this }; }
485        MUTATE_FRIEND
486};
487
488/// Type of one constant `1`
489class OneType final : public Type {
490public:
491        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
492
493        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
494private:
495        OneType * clone() const override { return new OneType{ *this }; }
496        MUTATE_FRIEND
497};
498
499/// Parent type for scope-qualified types at global scope
500class GlobalScopeType final : public Type {
501public:
502        GlobalScopeType() : Type() {}
503
504        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
505private:
506        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
507        MUTATE_FRIEND
508};
509
510bool isUnboundType(const Type * type);
511
512}
513
514namespace std {
515        template<>
516        struct hash<typename ast::TypeEnvKey> {
517                size_t operator() (const ast::TypeEnvKey & x) const {
518                        const size_t p = 1000007;
519                        size_t res = reinterpret_cast<size_t>(x.base);
520                        res = p * res + x.formal_usage;
521                        res = p * res + x.expr_id;
522                        return res;
523                }
524        };
525}
526
527#undef MUTATE_FRIEND
528
529// Local Variables: //
530// tab-width: 4 //
531// mode: c++ //
532// compile-command: "make install" //
533// End: //
Note: See TracBrowser for help on using the repository browser.