source: src/GenPoly/ScrubTyVars.cc@ affb51b

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