source: src/GenPoly/ScrubTyVars.cc @ 0026d67

ADTast-experimental
Last change on this file since 0026d67 was 0026d67, checked in by Andrew Beach <ajbeach@…>, 17 months ago

Replaced Mangle::typeMode() with Mangle::mangleType(...), as it is how typeMode() was always used and it is shorter. Various other clean-up in the Mangler files.

  • Property mode set to 100644
File size: 8.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// ScrubTyVars.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Oct  7 15:42:00 2022
13// Update Count     : 5
14//
15
16#include <utility>                      // for pair
17
18#include "AST/Pass.hpp"
19#include "GenPoly.h"                    // for mangleType, TyVarMap, alignof...
20#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
21#include "ScrubTyVars.h"
22#include "SymTab/Mangler.h"             // for mangleType
23#include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
24#include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
25#include "SynTree/Mutator.h"            // for Mutator
26#include "SynTree/Type.h"               // for PointerType, TypeInstType, Type
27
28namespace GenPoly {
29        Type * ScrubTyVars::postmutate( TypeInstType * typeInst ) {
30                if ( ! tyVars ) {
31                        if ( typeInst->get_isFtype() ) {
32                                delete typeInst;
33                                return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
34                        } else {
35                                PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
36                                delete typeInst;
37                                return ret;
38                        }
39                }
40
41                TyVarMap::const_iterator tyVar = tyVars->find( typeInst->name );
42                if ( tyVar != tyVars->end() ) {
43                        switch ( tyVar->second.kind ) {
44                          case TypeDecl::Dtype:
45                          case TypeDecl::Ttype:
46                                {
47                                        PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
48                                        delete typeInst;
49                                        return ret;
50                                }
51                          case TypeDecl::Ftype:
52                                delete typeInst;
53                                return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
54                          default:
55                                assertf(false, "Unhandled tyvar kind: %d", tyVar->second.kind);
56                        } // switch
57                } // if
58                return typeInst;
59        }
60
61        Type * ScrubTyVars::mutateAggregateType( Type * ty ) {
62                if ( shouldScrub( ty ) ) {
63                        PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
64                        delete ty;
65                        return ret;
66                }
67                return ty;
68        }
69
70        Type * ScrubTyVars::postmutate( StructInstType * structInst ) {
71                return mutateAggregateType( structInst );
72        }
73
74        Type * ScrubTyVars::postmutate( UnionInstType * unionInst ) {
75                return mutateAggregateType( unionInst );
76        }
77
78        void ScrubTyVars::primeBaseScrub( Type * type ) {
79                // need to determine whether type needs to be scrubbed to determine whether
80                // automatic recursion is necessary
81                if ( Type * t = shouldScrub( type ) ) {
82                        visit_children = false;
83                        GuardValue( dynType );
84                        dynType = t;
85                }
86        }
87
88        Expression * ScrubTyVars::postmutate( SizeofExpr * szeof ) {
89                // sizeof( T ) => _sizeof_T parameter, which is the size of T
90                if ( dynType ) {
91                        Expression *expr = new NameExpr( sizeofName( mangleType( dynType ) ) );
92                        return expr;
93                } // if
94                return szeof;
95        }
96
97        Expression * ScrubTyVars::postmutate( AlignofExpr * algnof ) {
98                // alignof( T ) => _alignof_T parameter, which is the alignment of T
99                if ( dynType ) {
100                        Expression *expr = new NameExpr( alignofName( mangleType( dynType ) ) );
101                        return expr;
102                } // if
103                return algnof;
104        }
105
106        Type * ScrubTyVars::postmutate( PointerType * pointer ) {
107                if ( dynType ) {
108                        Type * ret = dynType->acceptMutator( *visitor );
109                        ret->get_qualifiers() |= pointer->get_qualifiers();
110                        pointer->base = nullptr;
111                        delete pointer;
112                        return ret;
113                }
114                return pointer;
115        }
116
117namespace {
118
119enum class ScrubMode {
120        FromMap,
121        DynamicFromMap,
122        All,
123};
124
125struct ScrubTypeVars :
126        public ast::WithGuards,
127        public ast::WithShortCircuiting,
128        public ast::WithVisitorRef<ScrubTypeVars> {
129
130        ScrubTypeVars( ScrubMode m, TypeVarMap const * tv ) :
131                        mode ( m ), typeVars( tv ) {}
132
133        void previsit( ast::TypeInstType const * ) { visit_children = false; }
134        void previsit( ast::StructInstType const * ) { visit_children = false; }
135        void previsit( ast::UnionInstType const * ) { visit_children = false; }
136        void previsit( ast::SizeofExpr const * expr ) { primeBaseScrub( expr->type ); }
137        void previsit( ast::AlignofExpr const * expr ) { primeBaseScrub( expr->type ); }
138        void previsit( ast::PointerType const * type ) { primeBaseScrub( type->base ); }
139
140        ast::Type const * postvisit( ast::TypeInstType const * type );
141        ast::Type const * postvisit( ast::StructInstType const * type );
142        ast::Type const * postvisit( ast::UnionInstType const * type );
143        ast::Expr const * postvisit( ast::SizeofExpr const * expr );
144        ast::Expr const * postvisit( ast::AlignofExpr const * expr );
145        ast::Type const * postvisit( ast::PointerType const * type );
146
147private:
148        ScrubMode const mode;
149        /// Type varriables to scrub.
150        TypeVarMap const * const typeVars;
151        /// Value cached by primeBaseScrub.
152        ast::Type const * dynType = nullptr;
153
154        /// Returns the type if it should be scrubbed, nullptr otherwise.
155        ast::Type const * shouldScrub( ast::Type const * type ) {
156                switch ( mode ) {
157                case ScrubMode::FromMap:
158                        return isPolyType( type, *typeVars );
159                case ScrubMode::DynamicFromMap:
160                        return isDynType( type, *typeVars );
161                case ScrubMode::All:
162                        return isPolyType( type );
163                default:
164                        assertf( false, "Invalid ScrubMode in shouldScrub." );
165                        throw;
166                }
167        }
168
169        void primeBaseScrub( ast::Type const * type ) {
170                // Need to determine whether type needs to be scrubbed to
171                // determine whether automatic recursion is necessary.
172                if ( ast::Type const * t = shouldScrub( type ) ) {
173                        visit_children = false;
174                        GuardValue( dynType ) = t;
175                }
176        }
177
178        ast::Type const * postvisitAggregateType(
179                        ast::BaseInstType const * type ) {
180                if ( !shouldScrub( type ) ) return type;
181                return new ast::PointerType( new ast::VoidType( type->qualifiers ) );
182        }
183};
184
185ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
186        // This implies that mode == ScrubMode::All.
187        if ( !typeVars ) {
188                if ( ast::TypeDecl::Ftype == type->kind ) {
189                        return new ast::PointerType(
190                                new ast::FunctionType( ast::FixedArgs ) );
191                } else {
192                        return new ast::PointerType(
193                                new ast::VoidType( type->qualifiers ) );
194                }
195        }
196
197        auto typeVar = typeVars->find( *type );
198        if ( typeVar == typeVars->end() ) {
199                return type;
200        }
201
202        switch ( typeVar->second.kind ) {
203        case ::TypeDecl::Dtype:
204        case ::TypeDecl::Ttype:
205                return new ast::PointerType(
206                        new ast::VoidType( type->qualifiers ) );
207        case ::TypeDecl::Ftype:
208                return new ast::PointerType(
209                        new ast::FunctionType( ast::VariableArgs ) );
210        default:
211                assertf( false,
212                        "Unhandled type variable kind: %d", typeVar->second.kind );
213                throw; // Just in case the assert is removed, stop here.
214        }
215}
216
217ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
218        return postvisitAggregateType( type );
219}
220
221ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
222        return postvisitAggregateType( type );
223}
224
225ast::Expr const * ScrubTypeVars::postvisit( ast::SizeofExpr const * expr ) {
226        // sizeof( T ) becomes the _sizeof_T parameter.
227        if ( dynType ) {
228                return new ast::NameExpr( expr->location,
229                        sizeofName( Mangle::mangleType( dynType ) ) );
230        } else {
231                return expr;
232        }
233}
234
235ast::Expr const * ScrubTypeVars::postvisit( ast::AlignofExpr const * expr ) {
236        // alignof( T ) becomes the _alignof_T parameter.
237        if ( dynType ) {
238                return new ast::NameExpr( expr->location,
239                        alignofName( Mangle::mangleType( dynType ) ) );
240        } else {
241                return expr;
242        }
243}
244
245ast::Type const * ScrubTypeVars::postvisit( ast::PointerType const * type ) {
246        if ( dynType ) {
247                ast::Type * ret = ast::mutate( dynType->accept( *visitor ) );
248                ret->qualifiers |= type->qualifiers;
249                return ret;
250        } else {
251                return type;
252        }
253}
254
255const ast::Node * scrubTypeVarsBase(
256                const ast::Node * target,
257                ScrubMode mode, const TypeVarMap * typeVars ) {
258        if ( ScrubMode::All == mode ) {
259                assert( nullptr == typeVars );
260        } else {
261                assert( nullptr != typeVars );
262        }
263        ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
264        return target->accept( visitor );
265}
266
267} // namespace
268
269template<>
270ast::Node const * scrubTypeVars<ast::Node>(
271        const ast::Node * target, const TypeVarMap & typeVars ) {
272        return scrubTypeVarsBase( target, ScrubMode::FromMap, &typeVars );
273}
274
275template<>
276ast::Node const * scrubTypeVarsDynamic<ast::Node>(
277        ast::Node const * target, const TypeVarMap & typeVars ) {
278        return scrubTypeVarsBase( target, ScrubMode::DynamicFromMap, &typeVars );
279}
280
281template<>
282ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) {
283        return scrubTypeVarsBase( target, ScrubMode::All, nullptr );
284}
285
286} // namespace GenPoly
287
288// Local Variables: //
289// tab-width: 4 //
290// mode: c++ //
291// compile-command: "make install" //
292// End: //
Note: See TracBrowser for help on using the repository browser.