source: src/AST/Type.hpp @ c1e66d9

Last change on this file since c1e66d9 was c1e66d9, checked in by JiadaL <j82liang@…>, 5 months ago

Fix designator value in enumerated array and implemented enumerated array with inlined enume declaration

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