source: src/GenPoly/ScrubTyVars.cc @ a46f7b6

ADTast-experimental
Last change on this file since a46f7b6 was c8837e5, checked in by Andrew Beach <ajbeach@…>, 21 months ago

Rewrite in GenPoly? to avoid mixing new AST and TyVarMap? (which internally has old AST code). Some nearby functions got writen out even though they are not used, and hence not tested.

  • 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 mangle, typeMode
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->name );
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::mangle( dynType, Mangle::typeMode() ) ) );
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::mangle( dynType, Mangle::typeMode() ) ) );
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.