source: src/GenPoly/ScrubTyVars.cc @ 8cbe732

Last change on this file since 8cbe732 was 2f61765, checked in by Andrew Beach <ajbeach@…>, 21 months ago

Fixed a clang warning and cleaned up the rest of the function.

  • Property mode set to 100644
File size: 7.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// 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        ast::TypeDecl::Kind kind;
181        // This implies that mode == ScrubMode::All.
182        if ( !typeVars ) {
183                kind = type->kind;
184        } else {
185                // Otherwise, only scrub the type var if it is in map.
186                auto typeVar = typeVars->find( *type );
187                if ( typeVar == typeVars->end() ) {
188                        return type;
189                }
190                kind = typeVar->second.kind;
191        }
192
193        switch ( kind ) {
194        case ast::TypeDecl::Dtype:
195        case ast::TypeDecl::Ttype:
196                return new ast::PointerType(
197                        new ast::VoidType( type->qualifiers ) );
198        case ast::TypeDecl::Ftype:
199                return new ast::PointerType(
200                        new ast::FunctionType( ast::VariableArgs ) );
201        default:
202                assertf( false, "Unhandled type variable kind: %d", kind );
203                throw; // Just in case the assert is removed, stop here.
204        }
205}
206
207ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
208        return postvisitAggregateType( type );
209}
210
211ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
212        return postvisitAggregateType( type );
213}
214
215ast::Expr const * ScrubTypeVars::postvisit( ast::SizeofExpr const * expr ) {
216        // sizeof( T ) becomes the _sizeof_T parameter.
217        if ( dynType ) {
218                return new ast::NameExpr( expr->location,
219                        sizeofName( Mangle::mangleType( dynType ) ) );
220        } else {
221                return expr;
222        }
223}
224
225ast::Expr const * ScrubTypeVars::postvisit( ast::AlignofExpr const * expr ) {
226        // alignof( T ) becomes the _alignof_T parameter.
227        if ( dynType ) {
228                return new ast::NameExpr( expr->location,
229                        alignofName( Mangle::mangleType( dynType ) ) );
230        } else {
231                return expr;
232        }
233}
234
235ast::Type const * ScrubTypeVars::postvisit( ast::PointerType const * type ) {
236        if ( dynType ) {
237                ast::Type * ret = ast::mutate( dynType->accept( *visitor ) );
238                ret->qualifiers |= type->qualifiers;
239                return ret;
240        } else {
241                return type;
242        }
243}
244
245} // namespace
246
247const ast::Node * scrubTypeVarsBase(
248                const ast::Node * node, const TypeVarMap * typeVars, ScrubMode mode ) {
249        if ( ScrubMode::All == mode ) {
250                assert( nullptr == typeVars );
251        } else {
252                assert( nullptr != typeVars );
253        }
254        ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
255        return node->accept( visitor );
256}
257
258} // namespace GenPoly
259
260// Local Variables: //
261// tab-width: 4 //
262// mode: c++ //
263// compile-command: "make install" //
264// End: //
Note: See TracBrowser for help on using the repository browser.