source: src/AST/Type.hpp @ 24d6572

ast-experimental
Last change on this file since 24d6572 was 24d6572, checked in by Fangren Yu <f37yu@…>, 12 months ago

Merge branch 'master' into ast-experimental

  • 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        ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
219                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
220
221        // array types are complete if they have a dimension expression or are
222        // VLAs ('*' in parameter declaration), and incomplete otherwise.
223        // See 6.7.6.2
224        bool isComplete() const override { return dimension || isVarLen; }
225
226        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
227private:
228        ArrayType * clone() const override { return new ArrayType{ *this }; }
229        MUTATE_FRIEND
230};
231
232/// Reference type `T&`
233class ReferenceType final : public Type {
234public:
235        ptr<Type> base;
236
237        ReferenceType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
238
239        unsigned referenceDepth() const override { return base->referenceDepth() + 1; }
240
241        // Since reference types act like value types, their size is the size of the base.
242        // This makes it simple to cast the empty tuple to a reference type, since casts that increase
243        // the number of values are disallowed.
244        unsigned size() const override { return base->size(); }
245
246        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
247private:
248        ReferenceType * clone() const override { return new ReferenceType{ *this }; }
249        MUTATE_FRIEND
250};
251
252/// Qualified type `P.C`
253class QualifiedType final : public Type {
254public:
255        ptr<Type> parent;
256        ptr<Type> child;
257
258        QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
259        : Type(q), parent(p), child(c) {}
260
261        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
262private:
263        QualifiedType * clone() const override { return new QualifiedType{ *this }; }
264        MUTATE_FRIEND
265};
266
267/// Type of a function `[R1, R2](*)(P1, P2, P3)`
268class FunctionType final : public Type {
269public:
270        using ForallList = std::vector<ptr<TypeInstType>>;
271        using AssertionList = std::vector<ptr<VariableExpr>>;
272        ForallList forall;
273        AssertionList assertions;
274
275        std::vector<ptr<Type>> returns;
276        std::vector<ptr<Type>> params;
277
278        /// Does the function accept a variable number of arguments following the arguments specified
279        /// in the parameters list.
280        /// This could be because of
281        /// - an ellipsis in a prototype declaration
282        /// - an unprototyped declaration
283        ArgumentFlag isVarArgs;
284
285        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
286        : Type(q), returns(), params(), isVarArgs(va) {}
287
288        FunctionType( const FunctionType & o ) = default;
289
290        /// true if either the parameters or return values contain a tttype
291        bool isTtype() const;
292        /// true if function parameters are unconstrained by prototype
293        bool isUnprototyped() const { return isVarArgs && params.size() == 0; }
294
295        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
296private:
297        FunctionType * clone() const override { return new FunctionType{ *this }; }
298        MUTATE_FRIEND
299};
300
301/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
302class BaseInstType : public Type {
303public:
304        std::vector<ptr<Expr>> params;
305        std::string name;
306        bool hoistType = false;
307
308        BaseInstType(
309                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
310        : Type(q, std::move(as)), params(), name(n) {}
311
312        BaseInstType(
313                const std::string& n, std::vector<ptr<Expr>> && params,
314                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
315        : Type(q, std::move(as)), params(std::move(params)), name(n) {}
316
317        BaseInstType( const BaseInstType & o ) = default;
318
319        /// Gets aggregate declaration this type refers to
320        virtual const AggregateDecl * aggr() const = 0;
321        /// Looks up member declarations with given name
322        std::vector<readonly<Decl>> lookup( const std::string & name ) const;
323
324private:
325        virtual BaseInstType * clone() const override = 0;
326        MUTATE_FRIEND
327};
328
329// Common implementation for the SUE instance types. Not to be used directly.
330template<typename decl_t>
331class SueInstType final : public BaseInstType {
332public:
333        using base_type = decl_t;
334        readonly<decl_t> base;
335
336        SueInstType(
337                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
338        : BaseInstType( n, q, std::move(as) ), base() {}
339
340        SueInstType(
341                const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
342
343        SueInstType(
344                const base_type * b, std::vector<ptr<Expr>> && params,
345                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
346
347        bool isComplete() const override;
348
349        const decl_t * aggr() const override { return base; }
350
351        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
352private:
353        SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; }
354        MUTATE_FRIEND
355};
356
357/// An instance of a struct type.
358using StructInstType = SueInstType<StructDecl>;
359
360/// An instance of a union type.
361using UnionInstType = SueInstType<UnionDecl>;
362
363/// An instance of an enum type.
364using EnumInstType = SueInstType<EnumDecl>;
365
366/// An instance of a trait type.
367class TraitInstType final : public BaseInstType {
368public:
369        readonly<TraitDecl> base;
370
371        TraitInstType(
372                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
373        : BaseInstType( n, q, std::move(as) ), base() {}
374
375        TraitInstType(
376                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
377
378        // not meaningful for TraitInstType
379        bool isComplete() const override { assert(false); }
380
381        const TraitDecl * aggr() const override { return base; }
382
383        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
384private:
385        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
386        MUTATE_FRIEND
387};
388
389struct TypeEnvKey;
390
391/// instance of named type alias (typedef or variable)
392class TypeInstType final : public BaseInstType {
393public:
394        readonly<TypeDecl> base;
395        // previously from renameTyVars; now directly use integer fields instead of synthesized strings
396        // a nonzero value of formal_usage indicates a formal type (only used in function type)
397        // a zero value of formal_usage indicates an actual type (referenced inside body of parametric structs and functions)
398        TypeDecl::Kind kind;
399        int formal_usage = 0;
400        int expr_id = 0;
401
402        bool operator==(const TypeInstType & other) const;
403
404        TypeInstType(
405                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
406                std::vector<ptr<Attribute>> && as = {} )
407        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
408
409        TypeInstType( const TypeDecl * b,
410                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
411
412        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
413                std::vector<ptr<Attribute>> && as = {} )
414        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
415
416        TypeInstType( const TypeInstType & o ) = default;
417
418        TypeInstType( const TypeEnvKey & key );
419
420        /// sets `base`, updating `kind` correctly
421        void set_base( const TypeDecl * );
422
423        bool isComplete() const override;
424
425        // not meaningful for TypeInstType
426        const AggregateDecl * aggr() const override { assert(false); }
427
428        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
429
430        std::string typeString() const {
431                if (formal_usage > 0) return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + name;
432                else return name;
433        }
434private:
435        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
436        MUTATE_FRIEND
437};
438
439/// Compact representation of TypeInstType used for map lookups.
440struct TypeEnvKey {
441        const TypeDecl * base = nullptr;
442        int formal_usage = 0;
443        int expr_id = 0;
444
445        TypeEnvKey() = default;
446        TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0)
447        : base(base), formal_usage(formal_usage), expr_id(expr_id) {}
448        TypeEnvKey(const TypeInstType & inst)
449        : base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
450        std::string typeString() const;
451        bool operator==(const TypeEnvKey & other) const;
452        bool operator<(const TypeEnvKey & other) const;
453        operator bool() {return base;}
454};
455
456
457/// tuple type e.g. `[int, char]`
458class TupleType final : public Type {
459public:
460        std::vector<ptr<Type>> types;
461
462        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
463
464        // collection simulation
465        using iterator = std::vector<ptr<Type>>::const_iterator;
466        iterator begin() const { return types.begin(); }
467        iterator end() const { return types.end(); }
468
469        unsigned size() const override { return types.size(); }
470
471        const Type * getComponent( unsigned i ) const override {
472                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
473                        i, size() );
474                return *(begin()+i);
475        }
476
477        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
478private:
479        TupleType * clone() const override { return new TupleType{ *this }; }
480        MUTATE_FRIEND
481};
482
483/// Type of unresolved `typeof()` expression
484class TypeofType : public Type {
485public:
486        ptr<Expr> expr;
487        enum Kind { Typeof, Basetypeof } kind;
488
489        TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
490        : Type(q), expr(e), kind(k) {}
491
492        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
493private:
494        TypeofType * clone() const override { return new TypeofType{ *this }; }
495        MUTATE_FRIEND
496};
497
498/// Virtual Table Type `vtable(T)`
499class VTableType final : public Type {
500public:
501        ptr<Type> base;
502
503        VTableType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
504
505        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
506private:
507        VTableType * clone() const override { return new VTableType{ *this }; }
508        MUTATE_FRIEND
509};
510
511/// GCC built-in varargs type
512class VarArgsType final : public Type {
513public:
514        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
515
516        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
517private:
518        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
519        MUTATE_FRIEND
520};
521
522/// Type of zero constant `0`
523class ZeroType final : public Type {
524public:
525        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
526
527        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
528private:
529        ZeroType * clone() const override { return new ZeroType{ *this }; }
530        MUTATE_FRIEND
531};
532
533/// Type of one constant `1`
534class OneType final : public Type {
535public:
536        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
537
538        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
539private:
540        OneType * clone() const override { return new OneType{ *this }; }
541        MUTATE_FRIEND
542};
543
544/// Parent type for scope-qualified types at global scope
545class GlobalScopeType final : public Type {
546public:
547        GlobalScopeType() : Type() {}
548
549        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
550private:
551        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
552        MUTATE_FRIEND
553};
554
555bool isUnboundType(const Type * type);
556
557}
558
559namespace std {
560        template<>
561        struct hash<typename ast::TypeEnvKey> {
562                size_t operator() (const ast::TypeEnvKey & x) const {
563                        const size_t p = 1000007;
564                        size_t res = reinterpret_cast<size_t>(x.base);
565                        res = p * res + x.formal_usage;
566                        res = p * res + x.expr_id;
567                        return res;
568                }
569        };
570}
571
572#undef MUTATE_FRIEND
573
574// Local Variables: //
575// tab-width: 4 //
576// mode: c++ //
577// compile-command: "make install" //
578// End: //
Note: See TracBrowser for help on using the repository browser.