source: src/AST/Type.hpp @ e5c3811

arm-ehjacob/cs343-translationnew-ast-unique-expr
Last change on this file since e5c3811 was e5c3811, checked in by Fangren Yu <f37yu@…>, 14 months ago

create dedicated symbol tables for big 3 operators
note: arbitrary this param type is not supported; it is currently allowed although never used

  • Property mode set to 100644
File size: 16.9 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 Jul 23 14:15:00 2020
13// Update Count     : 6
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
39struct ForallSubstitutor;
40
41class Type : public Node {
42public:
43        CV::Qualifiers qualifiers;
44        std::vector<ptr<Attribute>> attributes;
45
46        Type( CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
47        : qualifiers(q), attributes(std::move(as)) {}
48
49        bool is_const() const { return qualifiers.is_const; }
50        bool is_volatile() const { return qualifiers.is_volatile; }
51        bool is_restrict() const { return qualifiers.is_restrict; }
52        bool is_mutex() const { return qualifiers.is_mutex; }
53        bool is_atomic() const { return qualifiers.is_atomic; }
54
55        Type * set_const( bool v ) { qualifiers.is_const = v; return this; }
56        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
57        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
58        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
59        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
60
61        /// How many elemental types are represented by this type
62        virtual unsigned size() const { return 1; }
63        /// Is this a void type?
64        virtual bool isVoid() const { return size() == 0; }
65        /// Get the i'th component of this type
66        virtual const Type * getComponent( unsigned i ) const;
67
68        /// type without outer pointers and arrays
69        const Type * stripDeclarator() const;
70        /// type without outer references
71        const Type * stripReferences() const;
72        /// number of reference occuring consecutively on the outermost layer of this type
73        /// (i.e. do not count references nested within other types)
74        virtual unsigned referenceDepth() const { return 0; }
75        /// true iff type is complete type (i.e. compiler knows the size, alignment, and layout)
76        virtual bool isComplete() const { return true; }
77
78        virtual const Type * accept( Visitor & v ) const override = 0;
79private:
80        virtual Type * clone() const override = 0;
81        MUTATE_FRIEND
82};
83
84/// Clear/reset the qualifiers on this type, cloning only if necessary
85template< enum Node::ref_type ref_t >
86void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) {
87        if ( p->qualifiers.val != q.val ) p.get_and_mutate()->qualifiers = q;
88}
89
90/// Add the specified qualifiers to this type, cloning only if necessary
91template< enum Node::ref_type ref_t >
92void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
93        if ( ( p->qualifiers.val & q.val ) != q.val ) p.get_and_mutate()->qualifiers |= q;
94}
95
96/// Remove the specified qualifiers from this type, cloning only if necessary
97template< enum Node::ref_type ref_t >
98void remove_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
99        if ( ( p->qualifiers.val & q.val ) != 0 ) p.get_and_mutate()->qualifiers -= q;
100}
101
102/// `void`
103class VoidType final : public Type {
104public:
105        VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
106
107        unsigned size() const override { return 0; }
108        bool isVoid() const override { return true; }
109        bool isComplete() const override { return false; }
110
111        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
112private:
113        VoidType * clone() const override { return new VoidType{ *this }; }
114        MUTATE_FRIEND
115};
116
117/// Built-in arithmetic type
118class BasicType final : public Type {
119public:
120        // GENERATED START, DO NOT EDIT
121        // GENERATED BY BasicTypes-gen.cc
122        enum Kind {
123                Bool,
124                Char,
125                SignedChar,
126                UnsignedChar,
127                ShortSignedInt,
128                ShortUnsignedInt,
129                SignedInt,
130                UnsignedInt,
131                LongSignedInt,
132                LongUnsignedInt,
133                LongLongSignedInt,
134                LongLongUnsignedInt,
135                SignedInt128,
136                UnsignedInt128,
137                uFloat16,
138                uFloat16Complex,
139                uFloat32,
140                uFloat32Complex,
141                Float,
142                FloatComplex,
143                uFloat32x,
144                uFloat32xComplex,
145                uFloat64,
146                uFloat64Complex,
147                Double,
148                DoubleComplex,
149                uFloat64x,
150                uFloat64xComplex,
151                uuFloat80,
152                uFloat128,
153                uFloat128Complex,
154                uuFloat128,
155                LongDouble,
156                LongDoubleComplex,
157                uFloat128x,
158                uFloat128xComplex,
159                NUMBER_OF_BASIC_TYPES
160        } kind;
161        // GENERATED END
162
163        /// xxx -- MAX_INTEGER_TYPE should probably be in BasicTypes-gen.cc, rather than hardcoded here
164        enum { MAX_INTEGER_TYPE = UnsignedInt128 };
165
166        /// string names of basic types; generated to match with Kind
167        static const char *typeNames[];
168
169        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
170        : Type(q, std::move(as)), kind(k) {}
171
172        /// Check if this type represents an integer type
173        bool isInteger() const { return (unsigned)kind <= (unsigned)MAX_INTEGER_TYPE; }
174
175        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
176private:
177        BasicType * clone() const override { return new BasicType{ *this }; }
178        MUTATE_FRIEND
179};
180
181/// Pointer/array variable length?
182enum LengthFlag { FixedLen, VariableLen };
183
184/// Pointer/array static dimension?
185enum DimensionFlag { DynamicDim, StaticDim };
186
187/// Pointer type `T*`
188class PointerType final : public Type {
189public:
190        ptr<Type> base;
191
192        // In C99, pointer types can be qualified in many ways, e.g. `int a[ static 3 ]`
193        ptr<Expr> dimension;
194        LengthFlag isVarLen = FixedLen;
195        DimensionFlag isStatic = DynamicDim;
196
197        PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
198        PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
199                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
200
201        // true if this pointer is actually an array
202        bool isArray() const { return isVarLen || isStatic || dimension; }
203
204        bool isComplete() const override { return ! isVarLen; }
205
206        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
207private:
208        PointerType * clone() const override { return new PointerType{ *this }; }
209        MUTATE_FRIEND
210};
211
212/// Array type `T[]`
213class ArrayType final : public Type {
214public:
215        ptr<Type> base;
216        ptr<Expr> dimension;
217        LengthFlag isVarLen;
218        DimensionFlag isStatic;
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/// Base type for potentially forall-qualified types
270class ParameterizedType : public Type {
271protected:
272        /// initializes forall with substitutor
273        void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
274public:
275        using ForallList = std::vector<ptr<TypeDecl>>;
276        // using ForallList = std::vector<readonly<TypeDecl>>;
277
278        // using ForallList = std::vector<ptr<TypeInstType>>;
279        ForallList forall;
280        // using AssertionList = std::vector<ptr<VariableExpr>>;
281        // AssertionList assertions;
282
283        ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {},
284                std::vector<ptr<Attribute>> && as = {} )
285        : Type(q, std::move(as)), forall(std::move(fs)) {}
286
287        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
288        : Type(q, std::move(as)), forall() {}
289
290        // enforce use of ForallSubstitutor to copy parameterized type
291        ParameterizedType( const ParameterizedType & ) = delete;
292
293        ParameterizedType( ParameterizedType && ) = default;
294
295        // no need to change destructor, and operator= deleted in Node
296
297private:
298        virtual ParameterizedType * clone() const override = 0;
299        MUTATE_FRIEND
300};
301
302/// Function variable arguments flag
303enum ArgumentFlag { FixedArgs, VariableArgs };
304
305/// Type of a function `[R1, R2](*)(P1, P2, P3)`
306class FunctionType final : public ParameterizedType {
307public:
308        std::vector<ptr<Type>> returns;
309        std::vector<ptr<Type>> params;
310
311        /// Does the function accept a variable number of arguments following the arguments specified
312        /// in the parameters list.
313        /// This could be because of
314        /// - an ellipsis in a prototype declaration
315        /// - an unprototyped declaration
316        ArgumentFlag isVarArgs;
317
318        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
319        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
320
321        FunctionType( const FunctionType & o );
322
323        /// true if either the parameters or return values contain a tttype
324        bool isTtype() const;
325        /// true if function parameters are unconstrained by prototype
326        bool isUnprototyped() const { return isVarArgs && params.size() == 0; }
327
328        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
329private:
330        FunctionType * clone() const override { return new FunctionType{ *this }; }
331        MUTATE_FRIEND
332};
333
334/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
335class BaseInstType : public ParameterizedType {
336protected:
337        /// Initializes forall and parameters based on substitutor
338        void initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub );
339public:
340        std::vector<ptr<Expr>> params;
341        std::string name;
342        bool hoistType = false;
343
344        BaseInstType(
345                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
346        : ParameterizedType(q, std::move(as)), params(), name(n) {}
347
348        BaseInstType(
349                const std::string& n, std::vector<ptr<Expr>> && params,
350                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
351        : ParameterizedType(q, std::move(as)), params(std::move(params)), name(n) {}
352
353        BaseInstType( const BaseInstType & o );
354
355        /// Gets aggregate declaration this type refers to
356        virtual const AggregateDecl * aggr() const = 0;
357        /// Looks up member declarations with given name
358        std::vector<readonly<Decl>> lookup( const std::string & name ) const;
359
360private:
361        virtual BaseInstType * clone() const override = 0;
362        MUTATE_FRIEND
363};
364
365// Common implementation for the SUE instance types. Not to be used directly.
366template<typename decl_t>
367class SueInstType final : public BaseInstType {
368public:
369        using base_type = decl_t;
370        readonly<decl_t> base;
371
372        SueInstType(
373                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
374        : BaseInstType( n, q, std::move(as) ), base() {}
375
376        SueInstType(
377                const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
378
379        SueInstType(
380                const base_type * b, std::vector<ptr<Expr>> && params,
381                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
382
383        bool isComplete() const override;
384
385        const decl_t * aggr() const override { return base; }
386
387        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
388private:
389        SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; }
390        MUTATE_FRIEND
391};
392
393/// An instance of a struct type.
394using StructInstType = SueInstType<StructDecl>;
395
396/// An instance of a union type.
397using UnionInstType = SueInstType<UnionDecl>;
398
399/// An instance of an enum type.
400using EnumInstType = SueInstType<EnumDecl>;
401
402/// An instance of a trait type.
403class TraitInstType final : public BaseInstType {
404public:
405        readonly<TraitDecl> base;
406
407        TraitInstType(
408                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
409        : BaseInstType( n, q, std::move(as) ), base() {}
410
411        TraitInstType(
412                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
413
414        // not meaningful for TraitInstType
415        bool isComplete() const override { assert(false); }
416
417        const TraitDecl * aggr() const override { return base; }
418
419        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
420private:
421        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
422        MUTATE_FRIEND
423};
424
425/// instance of named type alias (typedef or variable)
426class TypeInstType final : public BaseInstType {
427public:
428        readonly<TypeDecl> base;
429        // int context;
430        TypeDecl::Kind kind;
431
432        TypeInstType(
433                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
434                std::vector<ptr<Attribute>> && as = {} )
435        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
436        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
437                std::vector<ptr<Attribute>> && as = {} )
438        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
439
440        TypeInstType( const TypeInstType & o );
441
442        /// sets `base`, updating `kind` correctly
443        void set_base( const TypeDecl * );
444
445        bool isComplete() const override;
446
447        // not meaningful for TypeInstType
448        const AggregateDecl * aggr() const override { assert(false); }
449
450        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
451private:
452        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
453        MUTATE_FRIEND
454};
455
456/// tuple type e.g. `[int, char]`
457class TupleType final : public Type {
458public:
459        std::vector<ptr<Type>> types;
460        std::vector<ptr<Decl>> members;
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/// GCC built-in varargs type
499class VarArgsType final : public Type {
500public:
501        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
502
503        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
504private:
505        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
506        MUTATE_FRIEND
507};
508
509/// Type of zero constant `0`
510class ZeroType final : public Type {
511public:
512        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
513
514        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
515private:
516        ZeroType * clone() const override { return new ZeroType{ *this }; }
517        MUTATE_FRIEND
518};
519
520/// Type of one constant `1`
521class OneType final : public Type {
522public:
523        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
524
525        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
526private:
527        OneType * clone() const override { return new OneType{ *this }; }
528        MUTATE_FRIEND
529};
530
531/// Parent type for scope-qualified types at global scope
532class GlobalScopeType final : public Type {
533public:
534        GlobalScopeType() : Type() {}
535
536        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
537private:
538        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
539        MUTATE_FRIEND
540};
541
542bool isUnboundType(const Type * type);
543
544}
545
546
547#undef MUTATE_FRIEND
548
549// Local Variables: //
550// tab-width: 4 //
551
552// mode: c++ //
553// compile-command: "make install" //
554// End: //
Note: See TracBrowser for help on using the repository browser.