source: src/AST/Type.hpp @ 9c447e2

Last change on this file since 9c447e2 was acb33f15, checked in by JiadaL <j82liang@…>, 2 months ago

Change enum conversion steps

  • Property mode set to 100644
File size: 16.8 KB
RevLine 
[2bb4a01]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
[923d25a]11// Last Modified By : Andrew Beach
[fac05b3]12// Last Modified On : Thu Apr  6 15:58:00 2023
13// Update Count     : 9
[2bb4a01]14//
15
16#pragma once
17
[9e1d485]18#include <cassert>
19#include <cstddef>           // for nullptr_t
20#include <cstdint>           // for uintptr_t
21#include <utility>           // for move
22#include <vector>
23
[7a780ad]24#include "BasicKind.hpp"     // for BasicKind
[9e1d485]25#include "CVQualifiers.hpp"
[9b4f329]26#include "Decl.hpp"          // for AggregateDecl subclasses
[9e1d485]27#include "Fwd.hpp"
[d76c588]28#include "Node.hpp"          // for Node, ptr, ptr_base
[9e1d485]29#include "Visitor.hpp"
[2bb4a01]30
[f3cc5b6]31// Must be included in *all* AST classes; should be #undef'd at the end of the file
[99da267]32#define MUTATE_FRIEND \
[fc1a3e2]33        template<typename node_t> friend node_t * mutate(const node_t * node); \
[99da267]34        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
[f3cc5b6]35
[2bb4a01]36namespace ast {
37
38class Type : public Node {
[9e1d485]39public:
[54e41b3]40        CV::Qualifiers qualifiers;
[c829320]41        std::vector<ptr<Attribute>> attributes;
[87701b6]42
[1ae47de]43        Type( CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[c829320]44        : qualifiers(q), attributes(std::move(as)) {}
[54e41b3]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
[76ed81f]52        Type * set_const( bool v ) { qualifiers.is_const = v; return this; }
[dafe9e1]53        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
[76ed81f]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; }
[9e1d485]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
[d76c588]63        virtual const Type * getComponent( unsigned i ) const;
[9e1d485]64
65        /// type without outer pointers and arrays
[d76c588]66        const Type * stripDeclarator() const;
[9e1d485]67        /// type without outer references
[d76c588]68        const Type * stripReferences() const;
[9e1d485]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
[69bafd2]75        virtual const Type * accept( Visitor & v ) const override = 0;
[9e1d485]76private:
77        virtual Type * clone() const override = 0;
[f3cc5b6]78        MUTATE_FRIEND
[9e1d485]79};
80
[ee574a2]81/// Clear/reset the qualifiers on this type, cloning only if necessary
[d76c588]82template< enum Node::ref_type ref_t >
[ee574a2]83void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) {
[3606fe4]84        if ( p->qualifiers != q ) p.get_and_mutate()->qualifiers = q;
[d76c588]85}
86
[ee574a2]87/// Add the specified qualifiers to this type, cloning only if necessary
[d76c588]88template< enum Node::ref_type ref_t >
[ee574a2]89void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
[3606fe4]90        if ( ( p->qualifiers & q ) != q ) p.get_and_mutate()->qualifiers |= q;
[ee574a2]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 ) {
[3606fe4]96        if ( ( p->qualifiers & q ) != 0 ) p.get_and_mutate()->qualifiers -= q;
[d76c588]97}
98
[9e1d485]99/// `void`
100class VoidType final : public Type {
101public:
102        VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
[87701b6]103
[9e1d485]104        unsigned size() const override { return 0; }
105        bool isVoid() const override { return true; }
106        bool isComplete() const override { return false; }
107
[69bafd2]108        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]109private:
110        VoidType * clone() const override { return new VoidType{ *this }; }
[f3cc5b6]111        MUTATE_FRIEND
[9e1d485]112};
113
114/// Built-in arithmetic type
115class BasicType final : public Type {
116public:
[7a780ad]117        BasicKind kind;
[9e1d485]118
119        /// string names of basic types; generated to match with Kind
120        static const char *typeNames[];
121
[7a780ad]122        BasicType( BasicKind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[0f6a7752]123        : Type(q, std::move(as)), kind(k) {}
[9e1d485]124
125        /// Check if this type represents an integer type
[7a780ad]126        bool isInteger() const { return kind <= MAX_INTEGER_TYPE; }
[9e1d485]127
[69bafd2]128        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]129private:
130        BasicType * clone() const override { return new BasicType{ *this }; }
[f3cc5b6]131        MUTATE_FRIEND
[9e1d485]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() {}
[87701b6]151        PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
[9e1d485]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
[69bafd2]159        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]160private:
161        PointerType * clone() const override { return new PointerType{ *this }; }
[f3cc5b6]162        MUTATE_FRIEND
[9e1d485]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;
[2bb4a01]172
[87701b6]173        ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
[9e1d485]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
[69bafd2]181        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]182private:
183        ArrayType * clone() const override { return new ArrayType{ *this }; }
[f3cc5b6]184        MUTATE_FRIEND
[9e1d485]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
[69bafd2]201        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]202private:
203        ReferenceType * clone() const override { return new ReferenceType{ *this }; }
[f3cc5b6]204        MUTATE_FRIEND
[2bb4a01]205};
206
[9e1d485]207/// Qualified type `P.C`
208class QualifiedType final : public Type {
209public:
210        ptr<Type> parent;
211        ptr<Type> child;
212
[87701b6]213        QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
[9e1d485]214        : Type(q), parent(p), child(c) {}
215
[69bafd2]216        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]217private:
218        QualifiedType * clone() const override { return new QualifiedType{ *this }; }
[f3cc5b6]219        MUTATE_FRIEND
[9e1d485]220};
221
222/// Type of a function `[R1, R2](*)(P1, P2, P3)`
[361bf01]223class FunctionType final : public Type {
[9e1d485]224public:
[3e5dd913]225        using ForallList = std::vector<ptr<TypeInstType>>;
226        using AssertionList = std::vector<ptr<VariableExpr>>;
[361bf01]227        ForallList forall;
[3e5dd913]228        AssertionList assertions;
[361bf01]229
[954c954]230        std::vector<ptr<Type>> returns;
231        std::vector<ptr<Type>> params;
[9e1d485]232
[87701b6]233        /// Does the function accept a variable number of arguments following the arguments specified
[9e1d485]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 = {} )
[361bf01]241        : Type(q), returns(), params(), isVarArgs(va) {}
[9e1d485]242
[3e5dd913]243        FunctionType( const FunctionType & o ) = default;
[e0e9a0b]244
[9e1d485]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
[54e41b3]248        bool isUnprototyped() const { return isVarArgs && params.size() == 0; }
[9e1d485]249
[69bafd2]250        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]251private:
252        FunctionType * clone() const override { return new FunctionType{ *this }; }
[f3cc5b6]253        MUTATE_FRIEND
[9e1d485]254};
255
256/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
[361bf01]257class BaseInstType : public Type {
[9e1d485]258public:
[54e41b3]259        std::vector<ptr<Expr>> params;
[9e1d485]260        std::string name;
261        bool hoistType = false;
262
[98e8b3b]263        BaseInstType(
[e0e9a0b]264                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[361bf01]265        : Type(q, std::move(as)), params(), name(n) {}
[9e1d485]266
[3aec25f]267        BaseInstType(
268                const std::string& n, std::vector<ptr<Expr>> && params,
269                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[361bf01]270        : Type(q, std::move(as)), params(std::move(params)), name(n) {}
[3aec25f]271
[361bf01]272        BaseInstType( const BaseInstType & o ) = default;
[e0e9a0b]273
[9e1d485]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:
[98e8b3b]280        virtual BaseInstType * clone() const override = 0;
[f3cc5b6]281        MUTATE_FRIEND
[9e1d485]282};
283
[923d25a]284// Common implementation for the SUE instance types. Not to be used directly.
285template<typename decl_t>
[98e8b3b]286class SueInstType final : public BaseInstType {
[9e1d485]287public:
[923d25a]288        using base_type = decl_t;
289        readonly<decl_t> base;
[9e1d485]290
[923d25a]291        SueInstType(
[e0e9a0b]292                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[98e8b3b]293        : BaseInstType( n, q, std::move(as) ), base() {}
[e0e9a0b]294
[923d25a]295        SueInstType(
[3aec25f]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 = {} );
[87701b6]301
[9e1d485]302        bool isComplete() const override;
303
[923d25a]304        const decl_t * aggr() const override { return base; }
[9e1d485]305
[69bafd2]306        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]307private:
[923d25a]308        SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; }
[f3cc5b6]309        MUTATE_FRIEND
[9e1d485]310};
311
[923d25a]312/// An instance of a struct type.
313using StructInstType = SueInstType<StructDecl>;
[9e1d485]314
[923d25a]315/// An instance of a union type.
316using UnionInstType = SueInstType<UnionDecl>;
[9e1d485]317
[923d25a]318/// An instance of an enum type.
319using EnumInstType = SueInstType<EnumDecl>;
[9e1d485]320
[923d25a]321/// An instance of a trait type.
[98e8b3b]322class TraitInstType final : public BaseInstType {
[9e1d485]323public:
324        readonly<TraitDecl> base;
325
[f53acdf8]326        TraitInstType(
[e0e9a0b]327                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
[98e8b3b]328        : BaseInstType( n, q, std::move(as) ), base() {}
[f53acdf8]329
330        TraitInstType(
[e0e9a0b]331                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
[87701b6]332
[9e1d485]333        // not meaningful for TraitInstType
334        bool isComplete() const override { assert(false); }
335
336        const TraitDecl * aggr() const override { return base; }
337
[69bafd2]338        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]339private:
340        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
[f3cc5b6]341        MUTATE_FRIEND
[9e1d485]342};
343
[93c10de]344struct TypeEnvKey;
345
[9e1d485]346/// instance of named type alias (typedef or variable)
[98e8b3b]347class TypeInstType final : public BaseInstType {
[9e1d485]348public:
349        readonly<TypeDecl> base;
[3e5dd913]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)
[07de76b]353        TypeDecl::Kind kind;
[c9f6983]354        int formal_usage = 0;
355        int expr_id = 0;
[3e5dd913]356
[63d1ebe]357        bool operator==(const TypeInstType & other) const;
[9e1d485]358
[f53acdf8]359        TypeInstType(
[e0e9a0b]360                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
[9e1d485]361                std::vector<ptr<Attribute>> && as = {} )
[98e8b3b]362        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
[b230091]363
364        TypeInstType( const TypeDecl * b,
365                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
366
[07de76b]367        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
[9e1d485]368                std::vector<ptr<Attribute>> && as = {} )
[98e8b3b]369        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
[9e1d485]370
[361bf01]371        TypeInstType( const TypeInstType & o ) = default;
[e0e9a0b]372
[8fd53b6e]373        explicit TypeInstType( const TypeEnvKey & key );
[3e5dd913]374
[9e1d485]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
[69bafd2]383        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[3e5dd913]384
[bc179fd3]385        std::string typeString() const {
386                if (formal_usage > 0) return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + name;
[3e5dd913]387                else return name;
388        }
[9e1d485]389private:
390        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
[f3cc5b6]391        MUTATE_FRIEND
[9e1d485]392};
393
[93c10de]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;
[46da46b]408        operator bool() {return base;}
[93c10de]409};
410
[46da46b]411
[9e1d485]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(); }
[87701b6]423
[9e1d485]424        unsigned size() const override { return types.size(); }
425
[d76c588]426        const Type * getComponent( unsigned i ) const override {
[87701b6]427                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
[9e1d485]428                        i, size() );
429                return *(begin()+i);
430        }
431
[69bafd2]432        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]433private:
434        TupleType * clone() const override { return new TupleType{ *this }; }
[f3cc5b6]435        MUTATE_FRIEND
[9e1d485]436};
437
438/// Type of unresolved `typeof()` expression
439class TypeofType : public Type {
440public:
441        ptr<Expr> expr;
442        enum Kind { Typeof, Basetypeof } kind;
443
[87701b6]444        TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
[9e1d485]445        : Type(q), expr(e), kind(k) {}
446
[69bafd2]447        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]448private:
449        TypeofType * clone() const override { return new TypeofType{ *this }; }
[f3cc5b6]450        MUTATE_FRIEND
[9e1d485]451};
452
[b238618]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
[9e1d485]466/// GCC built-in varargs type
467class VarArgsType final : public Type {
468public:
469        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
[87701b6]470
[69bafd2]471        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]472private:
473        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
[f3cc5b6]474        MUTATE_FRIEND
[9e1d485]475};
476
477/// Type of zero constant `0`
478class ZeroType final : public Type {
479public:
480        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
[87701b6]481
[69bafd2]482        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]483private:
[f3cc5b6]484        ZeroType * clone() const override { return new ZeroType{ *this }; }
485        MUTATE_FRIEND
[9e1d485]486};
487
488/// Type of one constant `1`
489class OneType final : public Type {
490public:
491        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
492
[69bafd2]493        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]494private:
495        OneType * clone() const override { return new OneType{ *this }; }
[f3cc5b6]496        MUTATE_FRIEND
[9e1d485]497};
498
499/// Parent type for scope-qualified types at global scope
500class GlobalScopeType final : public Type {
501public:
[746ae82]502        GlobalScopeType() : Type() {}
[9e1d485]503
[69bafd2]504        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
[9e1d485]505private:
506        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
[f3cc5b6]507        MUTATE_FRIEND
[9e1d485]508};
[e0115286]509
[e5c3811]510bool isUnboundType(const Type * type);
511
[2bb4a01]512}
513
[3e5dd913]514namespace std {
515        template<>
[93c10de]516        struct hash<typename ast::TypeEnvKey> {
517                size_t operator() (const ast::TypeEnvKey & x) const {
[3e5dd913]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;
[bc179fd3]523                }
[3e5dd913]524        };
525}
526
[f3cc5b6]527#undef MUTATE_FRIEND
528
[2bb4a01]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.