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

ADT ast-experimental
Last change on this file since 466787a was ea2ed3a, checked in by Andrew Beach <ajbeach@…>, 3 years 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.