source: src/GenPoly/ScrubTyVars.cc @ 2125443a

ADTast-experimental
Last change on this file since 2125443a was ea2ed3a, checked in by Andrew Beach <ajbeach@…>, 16 months ago

Reorganize ScrubTyVars?, the Node specialization trick is redundent when there are three functions with the same base.

  • Property mode set to 100644
File size: 8.0 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 : Wed Dec  7 17:01:00 2022
13// Update Count     : 6
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
119struct ScrubTypeVars :
120        public ast::WithGuards,
121        public ast::WithShortCircuiting,
122        public ast::WithVisitorRef<ScrubTypeVars> {
123
124        ScrubTypeVars( ScrubMode m, TypeVarMap const * tv ) :
125                        mode ( m ), typeVars( tv ) {}
126
127        void previsit( ast::TypeInstType const * ) { visit_children = false; }
128        void previsit( ast::StructInstType const * ) { visit_children = false; }
129        void previsit( ast::UnionInstType const * ) { visit_children = false; }
130        void previsit( ast::SizeofExpr const * expr ) { primeBaseScrub( expr->type ); }
131        void previsit( ast::AlignofExpr const * expr ) { primeBaseScrub( expr->type ); }
132        void previsit( ast::PointerType const * type ) { primeBaseScrub( type->base ); }
133
134        ast::Type const * postvisit( ast::TypeInstType const * type );
135        ast::Type const * postvisit( ast::StructInstType const * type );
136        ast::Type const * postvisit( ast::UnionInstType const * type );
137        ast::Expr const * postvisit( ast::SizeofExpr const * expr );
138        ast::Expr const * postvisit( ast::AlignofExpr const * expr );
139        ast::Type const * postvisit( ast::PointerType const * type );
140
141private:
142        ScrubMode const mode;
143        /// Type varriables to scrub.
144        TypeVarMap const * const typeVars;
145        /// Value cached by primeBaseScrub.
146        ast::Type const * dynType = nullptr;
147
148        /// Returns the type if it should be scrubbed, nullptr otherwise.
149        ast::Type const * shouldScrub( ast::Type const * type ) {
150                switch ( mode ) {
151                case ScrubMode::FromMap:
152                        return isPolyType( type, *typeVars );
153                case ScrubMode::DynamicFromMap:
154                        return isDynType( type, *typeVars );
155                case ScrubMode::All:
156                        return isPolyType( type );
157                default:
158                        assertf( false, "Invalid ScrubMode in shouldScrub." );
159                        throw;
160                }
161        }
162
163        void primeBaseScrub( ast::Type const * type ) {
164                // Need to determine whether type needs to be scrubbed to
165                // determine whether automatic recursion is necessary.
166                if ( ast::Type const * t = shouldScrub( type ) ) {
167                        visit_children = false;
168                        GuardValue( dynType ) = t;
169                }
170        }
171
172        ast::Type const * postvisitAggregateType(
173                        ast::BaseInstType const * type ) {
174                if ( !shouldScrub( type ) ) return type;
175                return new ast::PointerType( new ast::VoidType( type->qualifiers ) );
176        }
177};
178
179ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
180        // This implies that mode == ScrubMode::All.
181        if ( !typeVars ) {
182                if ( ast::TypeDecl::Ftype == type->kind ) {
183                        return new ast::PointerType(
184                                new ast::FunctionType( ast::FixedArgs ) );
185                } else {
186                        return new ast::PointerType(
187                                new ast::VoidType( type->qualifiers ) );
188                }
189        }
190
191        auto typeVar = typeVars->find( *type );
192        if ( typeVar == typeVars->end() ) {
193                return type;
194        }
195
196        switch ( typeVar->second.kind ) {
197        case ::TypeDecl::Dtype:
198        case ::TypeDecl::Ttype:
199                return new ast::PointerType(
200                        new ast::VoidType( type->qualifiers ) );
201        case ::TypeDecl::Ftype:
202                return new ast::PointerType(
203                        new ast::FunctionType( ast::VariableArgs ) );
204        default:
205                assertf( false,
206                        "Unhandled type variable kind: %d", typeVar->second.kind );
207                throw; // Just in case the assert is removed, stop here.
208        }
209}
210
211ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
212        return postvisitAggregateType( type );
213}
214
215ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
216        return postvisitAggregateType( type );
217}
218
219ast::Expr const * ScrubTypeVars::postvisit( ast::SizeofExpr const * expr ) {
220        // sizeof( T ) becomes the _sizeof_T parameter.
221        if ( dynType ) {
222                return new ast::NameExpr( expr->location,
223                        sizeofName( Mangle::mangleType( dynType ) ) );
224        } else {
225                return expr;
226        }
227}
228
229ast::Expr const * ScrubTypeVars::postvisit( ast::AlignofExpr const * expr ) {
230        // alignof( T ) becomes the _alignof_T parameter.
231        if ( dynType ) {
232                return new ast::NameExpr( expr->location,
233                        alignofName( Mangle::mangleType( dynType ) ) );
234        } else {
235                return expr;
236        }
237}
238
239ast::Type const * ScrubTypeVars::postvisit( ast::PointerType const * type ) {
240        if ( dynType ) {
241                ast::Type * ret = ast::mutate( dynType->accept( *visitor ) );
242                ret->qualifiers |= type->qualifiers;
243                return ret;
244        } else {
245                return type;
246        }
247}
248
249} // namespace
250
251const ast::Node * scrubTypeVarsBase(
252                const ast::Node * node, const TypeVarMap * typeVars, ScrubMode mode ) {
253        if ( ScrubMode::All == mode ) {
254                assert( nullptr == typeVars );
255        } else {
256                assert( nullptr != typeVars );
257        }
258        ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
259        return node->accept( visitor );
260}
261
262} // namespace GenPoly
263
264// Local Variables: //
265// tab-width: 4 //
266// mode: c++ //
267// compile-command: "make install" //
268// End: //
Note: See TracBrowser for help on using the repository browser.